diff options
author | Dave Chinner <dchinner@redhat.com> | 2014-06-06 01:01:58 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-06-06 01:01:58 -0400 |
commit | 0650b55497ef583c43d6afc80e11a39e92d9a525 (patch) | |
tree | 7605714c36579ac623f4045db2fcb08ca9d298a5 | |
parent | 2d6dcc6d7e95cc83046b2f97e179e6bbb7921245 (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.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_attr_list.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 18 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 73 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 3 |
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; | |||
25 | struct zone; | 25 | struct zone; |
26 | struct xfs_dir_ops; | 26 | struct 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 | */ | ||
33 | struct 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 | */ |
44 | typedef struct xfs_da_args { | 61 | typedef 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 | ||
88 | void | 88 | int |
89 | xfs_dir_mount( | 89 | xfs_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 | |||
155 | void | ||
156 | xfs_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 | */ |
114 | extern void xfs_dir_startup(void); | 114 | extern void xfs_dir_startup(void); |
115 | extern void xfs_dir_mount(struct xfs_mount *mp); | 115 | extern int xfs_da_mount(struct xfs_mount *mp); |
116 | extern void xfs_da_unmount(struct xfs_mount *mp); | ||
117 | |||
116 | extern int xfs_dir_isempty(struct xfs_inode *dp); | 118 | extern int xfs_dir_isempty(struct xfs_inode *dp); |
117 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, | 119 | extern 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; | |||
27 | struct xfs_ail; | 27 | struct xfs_ail; |
28 | struct xfs_quotainfo; | 28 | struct xfs_quotainfo; |
29 | struct xfs_dir_ops; | 29 | struct xfs_dir_ops; |
30 | struct 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 */ |