diff options
Diffstat (limited to 'fs/xfs/xfs_ialloc.c')
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index c5836b951d0c..a64dfbd565a5 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -107,6 +107,16 @@ xfs_ialloc_log_di( | |||
107 | /* | 107 | /* |
108 | * Allocation group level functions. | 108 | * Allocation group level functions. |
109 | */ | 109 | */ |
110 | static inline int | ||
111 | xfs_ialloc_cluster_alignment( | ||
112 | xfs_alloc_arg_t *args) | ||
113 | { | ||
114 | if (xfs_sb_version_hasalign(&args->mp->m_sb) && | ||
115 | args->mp->m_sb.sb_inoalignmt >= | ||
116 | XFS_B_TO_FSBT(args->mp, XFS_INODE_CLUSTER_SIZE(args->mp))) | ||
117 | return args->mp->m_sb.sb_inoalignmt; | ||
118 | return 1; | ||
119 | } | ||
110 | 120 | ||
111 | /* | 121 | /* |
112 | * Allocate new inodes in the allocation group specified by agbp. | 122 | * Allocate new inodes in the allocation group specified by agbp. |
@@ -167,10 +177,24 @@ xfs_ialloc_ag_alloc( | |||
167 | args.mod = args.total = args.wasdel = args.isfl = | 177 | args.mod = args.total = args.wasdel = args.isfl = |
168 | args.userdata = args.minalignslop = 0; | 178 | args.userdata = args.minalignslop = 0; |
169 | args.prod = 1; | 179 | args.prod = 1; |
170 | args.alignment = 1; | 180 | |
171 | /* | 181 | /* |
172 | * Allow space for the inode btree to split. | 182 | * We need to take into account alignment here to ensure that |
183 | * we don't modify the free list if we fail to have an exact | ||
184 | * block. If we don't have an exact match, and every oher | ||
185 | * attempt allocation attempt fails, we'll end up cancelling | ||
186 | * a dirty transaction and shutting down. | ||
187 | * | ||
188 | * For an exact allocation, alignment must be 1, | ||
189 | * however we need to take cluster alignment into account when | ||
190 | * fixing up the freelist. Use the minalignslop field to | ||
191 | * indicate that extra blocks might be required for alignment, | ||
192 | * but not to use them in the actual exact allocation. | ||
173 | */ | 193 | */ |
194 | args.alignment = 1; | ||
195 | args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1; | ||
196 | |||
197 | /* Allow space for the inode btree to split. */ | ||
174 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; | 198 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; |
175 | if ((error = xfs_alloc_vextent(&args))) | 199 | if ((error = xfs_alloc_vextent(&args))) |
176 | return error; | 200 | return error; |
@@ -191,13 +215,8 @@ xfs_ialloc_ag_alloc( | |||
191 | ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN)); | 215 | ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN)); |
192 | args.alignment = args.mp->m_dalign; | 216 | args.alignment = args.mp->m_dalign; |
193 | isaligned = 1; | 217 | isaligned = 1; |
194 | } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) && | 218 | } else |
195 | args.mp->m_sb.sb_inoalignmt >= | 219 | args.alignment = xfs_ialloc_cluster_alignment(&args); |
196 | XFS_B_TO_FSBT(args.mp, | ||
197 | XFS_INODE_CLUSTER_SIZE(args.mp))) | ||
198 | args.alignment = args.mp->m_sb.sb_inoalignmt; | ||
199 | else | ||
200 | args.alignment = 1; | ||
201 | /* | 220 | /* |
202 | * Need to figure out where to allocate the inode blocks. | 221 | * Need to figure out where to allocate the inode blocks. |
203 | * Ideally they should be spaced out through the a.g. | 222 | * Ideally they should be spaced out through the a.g. |
@@ -230,12 +249,7 @@ xfs_ialloc_ag_alloc( | |||
230 | args.agbno = be32_to_cpu(agi->agi_root); | 249 | args.agbno = be32_to_cpu(agi->agi_root); |
231 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | 250 | args.fsbno = XFS_AGB_TO_FSB(args.mp, |
232 | be32_to_cpu(agi->agi_seqno), args.agbno); | 251 | be32_to_cpu(agi->agi_seqno), args.agbno); |
233 | if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) && | 252 | args.alignment = xfs_ialloc_cluster_alignment(&args); |
234 | args.mp->m_sb.sb_inoalignmt >= | ||
235 | XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp))) | ||
236 | args.alignment = args.mp->m_sb.sb_inoalignmt; | ||
237 | else | ||
238 | args.alignment = 1; | ||
239 | if ((error = xfs_alloc_vextent(&args))) | 253 | if ((error = xfs_alloc_vextent(&args))) |
240 | return error; | 254 | return error; |
241 | } | 255 | } |
@@ -271,7 +285,7 @@ xfs_ialloc_ag_alloc( | |||
271 | * use the old version so that old kernels will continue to be | 285 | * use the old version so that old kernels will continue to be |
272 | * able to use the file system. | 286 | * able to use the file system. |
273 | */ | 287 | */ |
274 | if (XFS_SB_VERSION_HASNLINK(&args.mp->m_sb)) | 288 | if (xfs_sb_version_hasnlink(&args.mp->m_sb)) |
275 | version = XFS_DINODE_VERSION_2; | 289 | version = XFS_DINODE_VERSION_2; |
276 | else | 290 | else |
277 | version = XFS_DINODE_VERSION_1; | 291 | version = XFS_DINODE_VERSION_1; |
@@ -1053,7 +1067,7 @@ xfs_difree( | |||
1053 | /* | 1067 | /* |
1054 | * When an inode cluster is free, it becomes eligible for removal | 1068 | * When an inode cluster is free, it becomes eligible for removal |
1055 | */ | 1069 | */ |
1056 | if ((mp->m_flags & XFS_MOUNT_IDELETE) && | 1070 | if (!(mp->m_flags & XFS_MOUNT_IKEEP) && |
1057 | (rec.ir_freecount == XFS_IALLOC_INODES(mp))) { | 1071 | (rec.ir_freecount == XFS_IALLOC_INODES(mp))) { |
1058 | 1072 | ||
1059 | *delete = 1; | 1073 | *delete = 1; |