diff options
| -rw-r--r-- | fs/xfs/xfs_inode_item.c | 165 |
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 | */ |
| 189 | STATIC void | 188 | STATIC void |
| 190 | xfs_inode_item_format( | 189 | xfs_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 | |||
| 210 | STATIC struct xfs_log_iovec * | ||
| 211 | xfs_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)) { | 330 | STATIC struct xfs_log_iovec * |
| 358 | iip->ili_fields &= | 331 | xfs_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 | ||
| 446 | out: | 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 | */ | ||
| 429 | STATIC void | ||
| 430 | xfs_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. |
