aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode_item.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-12 19:00:43 -0500
committerDave Chinner <david@fromorbit.com>2013-12-12 19:00:43 -0500
commit3de559fbd04d67473b9be2bd183823c40c4b7557 (patch)
treeaa3ba1c495f9a57362d4e9c77e6005bb43a44cde /fs/xfs/xfs_inode_item.c
parentce9641d6c981aad0463b2d1455f0b60e5c8671c5 (diff)
xfs: refactor xfs_inode_item_format
Split out a function to handle the data and attr fork, as well as a helper for the really old v1 inodes. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_inode_item.c')
-rw-r--r--fs/xfs/xfs_inode_item.c165
1 files changed, 89 insertions, 76 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 050d2540f7b4..2ad12dcf8311 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -180,63 +180,41 @@ xfs_inode_item_format_extents(
180} 180}
181 181
182/* 182/*
183 * This is called to fill in the vector of log iovecs for the 183 * If this is a v1 format inode, then we need to log it as such. This means
184 * given inode log item. It fills the first item with an inode 184 * that we have to copy the link count from the new field to the old. We
185 * log format structure, the second with the on-disk inode structure, 185 * don't have to worry about the new fields, because nothing trusts them as
186 * and a possible third and/or fourth with the inode data/extents/b-tree 186 * long as the old inode version number is there.
187 * root and inode attributes data/extents/b-tree root.
188 */ 187 */
189STATIC void 188STATIC void
190xfs_inode_item_format( 189xfs_inode_item_format_v1_inode(
191 struct xfs_log_item *lip, 190 struct xfs_inode *ip)
192 struct xfs_log_iovec *vecp) 191{
192 if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) {
193 /*
194 * Convert it back.
195 */
196 ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
197 ip->i_d.di_onlink = ip->i_d.di_nlink;
198 } else {
199 /*
200 * The superblock version has already been bumped,
201 * so just make the conversion to the new inode
202 * format permanent.
203 */
204 ip->i_d.di_version = 2;
205 ip->i_d.di_onlink = 0;
206 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
207 }
208}
209
210STATIC struct xfs_log_iovec *
211xfs_inode_item_format_data_fork(
212 struct xfs_inode_log_item *iip,
213 struct xfs_log_iovec *vecp,
214 int *nvecs)
193{ 215{
194 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
195 struct xfs_inode *ip = iip->ili_inode; 216 struct xfs_inode *ip = iip->ili_inode;
196 uint nvecs;
197 size_t data_bytes; 217 size_t data_bytes;
198 xfs_mount_t *mp;
199
200 vecp->i_addr = &iip->ili_format;
201 vecp->i_len = sizeof(xfs_inode_log_format_t);
202 vecp->i_type = XLOG_REG_TYPE_IFORMAT;
203 vecp++;
204 nvecs = 1;
205
206 vecp->i_addr = &ip->i_d;
207 vecp->i_len = xfs_icdinode_size(ip->i_d.di_version);
208 vecp->i_type = XLOG_REG_TYPE_ICORE;
209 vecp++;
210 nvecs++;
211
212 /*
213 * If this is really an old format inode, then we need to
214 * log it as such. This means that we have to copy the link
215 * count from the new field to the old. We don't have to worry
216 * about the new fields, because nothing trusts them as long as
217 * the old inode version number is there. If the superblock already
218 * has a new version number, then we don't bother converting back.
219 */
220 mp = ip->i_mount;
221 ASSERT(ip->i_d.di_version == 1 || xfs_sb_version_hasnlink(&mp->m_sb));
222 if (ip->i_d.di_version == 1) {
223 if (!xfs_sb_version_hasnlink(&mp->m_sb)) {
224 /*
225 * Convert it back.
226 */
227 ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
228 ip->i_d.di_onlink = ip->i_d.di_nlink;
229 } else {
230 /*
231 * The superblock version has already been bumped,
232 * so just make the conversion to the new inode
233 * format permanent.
234 */
235 ip->i_d.di_version = 2;
236 ip->i_d.di_onlink = 0;
237 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
238 }
239 }
240 218
241 switch (ip->i_d.di_format) { 219 switch (ip->i_d.di_format) {
242 case XFS_DINODE_FMT_EXTENTS: 220 case XFS_DINODE_FMT_EXTENTS:
@@ -271,12 +249,11 @@ xfs_inode_item_format(
271 ASSERT(vecp->i_len <= ip->i_df.if_bytes); 249 ASSERT(vecp->i_len <= ip->i_df.if_bytes);
272 iip->ili_format.ilf_dsize = vecp->i_len; 250 iip->ili_format.ilf_dsize = vecp->i_len;
273 vecp++; 251 vecp++;
274 nvecs++; 252 (*nvecs)++;
275 } else { 253 } else {
276 iip->ili_fields &= ~XFS_ILOG_DEXT; 254 iip->ili_fields &= ~XFS_ILOG_DEXT;
277 } 255 }
278 break; 256 break;
279
280 case XFS_DINODE_FMT_BTREE: 257 case XFS_DINODE_FMT_BTREE:
281 iip->ili_fields &= 258 iip->ili_fields &=
282 ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | 259 ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT |
@@ -289,7 +266,7 @@ xfs_inode_item_format(
289 vecp->i_len = ip->i_df.if_broot_bytes; 266 vecp->i_len = ip->i_df.if_broot_bytes;
290 vecp->i_type = XLOG_REG_TYPE_IBROOT; 267 vecp->i_type = XLOG_REG_TYPE_IBROOT;
291 vecp++; 268 vecp++;
292 nvecs++; 269 (*nvecs)++;
293 iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; 270 iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes;
294 } else { 271 } else {
295 ASSERT(!(iip->ili_fields & 272 ASSERT(!(iip->ili_fields &
@@ -297,7 +274,6 @@ xfs_inode_item_format(
297 iip->ili_fields &= ~XFS_ILOG_DBROOT; 274 iip->ili_fields &= ~XFS_ILOG_DBROOT;
298 } 275 }
299 break; 276 break;
300
301 case XFS_DINODE_FMT_LOCAL: 277 case XFS_DINODE_FMT_LOCAL:
302 iip->ili_fields &= 278 iip->ili_fields &=
303 ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | 279 ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT |
@@ -319,13 +295,12 @@ xfs_inode_item_format(
319 vecp->i_len = (int)data_bytes; 295 vecp->i_len = (int)data_bytes;
320 vecp->i_type = XLOG_REG_TYPE_ILOCAL; 296 vecp->i_type = XLOG_REG_TYPE_ILOCAL;
321 vecp++; 297 vecp++;
322 nvecs++; 298 (*nvecs)++;
323 iip->ili_format.ilf_dsize = (unsigned)data_bytes; 299 iip->ili_format.ilf_dsize = (unsigned)data_bytes;
324 } else { 300 } else {
325 iip->ili_fields &= ~XFS_ILOG_DDATA; 301 iip->ili_fields &= ~XFS_ILOG_DDATA;
326 } 302 }
327 break; 303 break;
328
329 case XFS_DINODE_FMT_DEV: 304 case XFS_DINODE_FMT_DEV:
330 iip->ili_fields &= 305 iip->ili_fields &=
331 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | 306 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
@@ -335,7 +310,6 @@ xfs_inode_item_format(
335 ip->i_df.if_u2.if_rdev; 310 ip->i_df.if_u2.if_rdev;
336 } 311 }
337 break; 312 break;
338
339 case XFS_DINODE_FMT_UUID: 313 case XFS_DINODE_FMT_UUID:
340 iip->ili_fields &= 314 iip->ili_fields &=
341 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | 315 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
@@ -345,20 +319,22 @@ xfs_inode_item_format(
345 ip->i_df.if_u2.if_uuid; 319 ip->i_df.if_u2.if_uuid;
346 } 320 }
347 break; 321 break;
348
349 default: 322 default:
350 ASSERT(0); 323 ASSERT(0);
351 break; 324 break;
352 } 325 }
353 326
354 /* 327 return vecp;
355 * If there are no attributes associated with the file, then we're done. 328}
356 */ 329
357 if (!XFS_IFORK_Q(ip)) { 330STATIC struct xfs_log_iovec *
358 iip->ili_fields &= 331xfs_inode_item_format_attr_fork(
359 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); 332 struct xfs_inode_log_item *iip,
360 goto out; 333 struct xfs_log_iovec *vecp,
361 } 334 int *nvecs)
335{
336 struct xfs_inode *ip = iip->ili_inode;
337 size_t data_bytes;
362 338
363 switch (ip->i_d.di_aformat) { 339 switch (ip->i_d.di_aformat) {
364 case XFS_DINODE_FMT_EXTENTS: 340 case XFS_DINODE_FMT_EXTENTS:
@@ -386,12 +362,11 @@ xfs_inode_item_format(
386#endif 362#endif
387 iip->ili_format.ilf_asize = vecp->i_len; 363 iip->ili_format.ilf_asize = vecp->i_len;
388 vecp++; 364 vecp++;
389 nvecs++; 365 (*nvecs)++;
390 } else { 366 } else {
391 iip->ili_fields &= ~XFS_ILOG_AEXT; 367 iip->ili_fields &= ~XFS_ILOG_AEXT;
392 } 368 }
393 break; 369 break;
394
395 case XFS_DINODE_FMT_BTREE: 370 case XFS_DINODE_FMT_BTREE:
396 iip->ili_fields &= 371 iip->ili_fields &=
397 ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT); 372 ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT);
@@ -404,13 +379,12 @@ xfs_inode_item_format(
404 vecp->i_len = ip->i_afp->if_broot_bytes; 379 vecp->i_len = ip->i_afp->if_broot_bytes;
405 vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; 380 vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT;
406 vecp++; 381 vecp++;
407 nvecs++; 382 (*nvecs)++;
408 iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; 383 iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes;
409 } else { 384 } else {
410 iip->ili_fields &= ~XFS_ILOG_ABROOT; 385 iip->ili_fields &= ~XFS_ILOG_ABROOT;
411 } 386 }
412 break; 387 break;
413
414 case XFS_DINODE_FMT_LOCAL: 388 case XFS_DINODE_FMT_LOCAL:
415 iip->ili_fields &= 389 iip->ili_fields &=
416 ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT); 390 ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT);
@@ -431,19 +405,59 @@ xfs_inode_item_format(
431 vecp->i_len = (int)data_bytes; 405 vecp->i_len = (int)data_bytes;
432 vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL; 406 vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL;
433 vecp++; 407 vecp++;
434 nvecs++; 408 (*nvecs)++;
435 iip->ili_format.ilf_asize = (unsigned)data_bytes; 409 iip->ili_format.ilf_asize = (unsigned)data_bytes;
436 } else { 410 } else {
437 iip->ili_fields &= ~XFS_ILOG_ADATA; 411 iip->ili_fields &= ~XFS_ILOG_ADATA;
438 } 412 }
439 break; 413 break;
440
441 default: 414 default:
442 ASSERT(0); 415 ASSERT(0);
443 break; 416 break;
444 } 417 }
445 418
446out: 419 return vecp;
420}
421
422/*
423 * This is called to fill in the vector of log iovecs for the given inode
424 * log item. It fills the first item with an inode log format structure,
425 * the second with the on-disk inode structure, and a possible third and/or
426 * fourth with the inode data/extents/b-tree root and inode attributes
427 * data/extents/b-tree root.
428 */
429STATIC void
430xfs_inode_item_format(
431 struct xfs_log_item *lip,
432 struct xfs_log_iovec *vecp)
433{
434 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
435 struct xfs_inode *ip = iip->ili_inode;
436 uint nvecs;
437
438 vecp->i_addr = &iip->ili_format;
439 vecp->i_len = sizeof(xfs_inode_log_format_t);
440 vecp->i_type = XLOG_REG_TYPE_IFORMAT;
441 vecp++;
442 nvecs = 1;
443
444 vecp->i_addr = &ip->i_d;
445 vecp->i_len = xfs_icdinode_size(ip->i_d.di_version);
446 vecp->i_type = XLOG_REG_TYPE_ICORE;
447 vecp++;
448 nvecs++;
449
450 if (ip->i_d.di_version == 1)
451 xfs_inode_item_format_v1_inode(ip);
452
453 vecp = xfs_inode_item_format_data_fork(iip, vecp, &nvecs);
454 if (XFS_IFORK_Q(ip)) {
455 vecp = xfs_inode_item_format_attr_fork(iip, vecp, &nvecs);
456 } else {
457 iip->ili_fields &=
458 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT);
459 }
460
447 /* 461 /*
448 * Now update the log format that goes out to disk from the in-core 462 * Now update the log format that goes out to disk from the in-core
449 * values. We always write the inode core to make the arithmetic 463 * values. We always write the inode core to make the arithmetic
@@ -455,7 +469,6 @@ out:
455 iip->ili_format.ilf_size = nvecs; 469 iip->ili_format.ilf_size = nvecs;
456} 470}
457 471
458
459/* 472/*
460 * This is called to pin the inode associated with the inode log 473 * This is called to pin the inode associated with the inode log
461 * item in memory so it cannot be written out. 474 * item in memory so it cannot be written out.