0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_inode_item.h"
0016 #include "xfs_trace.h"
0017 #include "xfs_trans_priv.h"
0018 #include "xfs_buf_item.h"
0019 #include "xfs_log.h"
0020 #include "xfs_log_priv.h"
0021 #include "xfs_error.h"
0022
0023 #include <linux/iversion.h>
0024
0025 struct kmem_cache *xfs_ili_cache;
0026
0027 static inline struct xfs_inode_log_item *INODE_ITEM(struct xfs_log_item *lip)
0028 {
0029 return container_of(lip, struct xfs_inode_log_item, ili_item);
0030 }
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 STATIC void
0047 xfs_inode_item_data_fork_size(
0048 struct xfs_inode_log_item *iip,
0049 int *nvecs,
0050 int *nbytes)
0051 {
0052 struct xfs_inode *ip = iip->ili_inode;
0053
0054 switch (ip->i_df.if_format) {
0055 case XFS_DINODE_FMT_EXTENTS:
0056 if ((iip->ili_fields & XFS_ILOG_DEXT) &&
0057 ip->i_df.if_nextents > 0 &&
0058 ip->i_df.if_bytes > 0) {
0059
0060 *nbytes += xfs_inode_data_fork_size(ip);
0061 *nvecs += 1;
0062 }
0063 break;
0064 case XFS_DINODE_FMT_BTREE:
0065 if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
0066 ip->i_df.if_broot_bytes > 0) {
0067 *nbytes += ip->i_df.if_broot_bytes;
0068 *nvecs += 1;
0069 }
0070 break;
0071 case XFS_DINODE_FMT_LOCAL:
0072 if ((iip->ili_fields & XFS_ILOG_DDATA) &&
0073 ip->i_df.if_bytes > 0) {
0074 *nbytes += xlog_calc_iovec_len(ip->i_df.if_bytes);
0075 *nvecs += 1;
0076 }
0077 break;
0078
0079 case XFS_DINODE_FMT_DEV:
0080 break;
0081 default:
0082 ASSERT(0);
0083 break;
0084 }
0085 }
0086
0087 STATIC void
0088 xfs_inode_item_attr_fork_size(
0089 struct xfs_inode_log_item *iip,
0090 int *nvecs,
0091 int *nbytes)
0092 {
0093 struct xfs_inode *ip = iip->ili_inode;
0094
0095 switch (ip->i_af.if_format) {
0096 case XFS_DINODE_FMT_EXTENTS:
0097 if ((iip->ili_fields & XFS_ILOG_AEXT) &&
0098 ip->i_af.if_nextents > 0 &&
0099 ip->i_af.if_bytes > 0) {
0100
0101 *nbytes += xfs_inode_attr_fork_size(ip);
0102 *nvecs += 1;
0103 }
0104 break;
0105 case XFS_DINODE_FMT_BTREE:
0106 if ((iip->ili_fields & XFS_ILOG_ABROOT) &&
0107 ip->i_af.if_broot_bytes > 0) {
0108 *nbytes += ip->i_af.if_broot_bytes;
0109 *nvecs += 1;
0110 }
0111 break;
0112 case XFS_DINODE_FMT_LOCAL:
0113 if ((iip->ili_fields & XFS_ILOG_ADATA) &&
0114 ip->i_af.if_bytes > 0) {
0115 *nbytes += xlog_calc_iovec_len(ip->i_af.if_bytes);
0116 *nvecs += 1;
0117 }
0118 break;
0119 default:
0120 ASSERT(0);
0121 break;
0122 }
0123 }
0124
0125
0126
0127
0128
0129
0130
0131
0132 STATIC void
0133 xfs_inode_item_size(
0134 struct xfs_log_item *lip,
0135 int *nvecs,
0136 int *nbytes)
0137 {
0138 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0139 struct xfs_inode *ip = iip->ili_inode;
0140
0141 *nvecs += 2;
0142 *nbytes += sizeof(struct xfs_inode_log_format) +
0143 xfs_log_dinode_size(ip->i_mount);
0144
0145 xfs_inode_item_data_fork_size(iip, nvecs, nbytes);
0146 if (xfs_inode_has_attr_fork(ip))
0147 xfs_inode_item_attr_fork_size(iip, nvecs, nbytes);
0148 }
0149
0150 STATIC void
0151 xfs_inode_item_format_data_fork(
0152 struct xfs_inode_log_item *iip,
0153 struct xfs_inode_log_format *ilf,
0154 struct xfs_log_vec *lv,
0155 struct xfs_log_iovec **vecp)
0156 {
0157 struct xfs_inode *ip = iip->ili_inode;
0158 size_t data_bytes;
0159
0160 switch (ip->i_df.if_format) {
0161 case XFS_DINODE_FMT_EXTENTS:
0162 iip->ili_fields &=
0163 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
0164
0165 if ((iip->ili_fields & XFS_ILOG_DEXT) &&
0166 ip->i_df.if_nextents > 0 &&
0167 ip->i_df.if_bytes > 0) {
0168 struct xfs_bmbt_rec *p;
0169
0170 ASSERT(xfs_iext_count(&ip->i_df) > 0);
0171
0172 p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IEXT);
0173 data_bytes = xfs_iextents_copy(ip, p, XFS_DATA_FORK);
0174 xlog_finish_iovec(lv, *vecp, data_bytes);
0175
0176 ASSERT(data_bytes <= ip->i_df.if_bytes);
0177
0178 ilf->ilf_dsize = data_bytes;
0179 ilf->ilf_size++;
0180 } else {
0181 iip->ili_fields &= ~XFS_ILOG_DEXT;
0182 }
0183 break;
0184 case XFS_DINODE_FMT_BTREE:
0185 iip->ili_fields &=
0186 ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | XFS_ILOG_DEV);
0187
0188 if ((iip->ili_fields & XFS_ILOG_DBROOT) &&
0189 ip->i_df.if_broot_bytes > 0) {
0190 ASSERT(ip->i_df.if_broot != NULL);
0191 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IBROOT,
0192 ip->i_df.if_broot,
0193 ip->i_df.if_broot_bytes);
0194 ilf->ilf_dsize = ip->i_df.if_broot_bytes;
0195 ilf->ilf_size++;
0196 } else {
0197 ASSERT(!(iip->ili_fields &
0198 XFS_ILOG_DBROOT));
0199 iip->ili_fields &= ~XFS_ILOG_DBROOT;
0200 }
0201 break;
0202 case XFS_DINODE_FMT_LOCAL:
0203 iip->ili_fields &=
0204 ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | XFS_ILOG_DEV);
0205 if ((iip->ili_fields & XFS_ILOG_DDATA) &&
0206 ip->i_df.if_bytes > 0) {
0207 ASSERT(ip->i_df.if_u1.if_data != NULL);
0208 ASSERT(ip->i_disk_size > 0);
0209 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL,
0210 ip->i_df.if_u1.if_data,
0211 ip->i_df.if_bytes);
0212 ilf->ilf_dsize = (unsigned)ip->i_df.if_bytes;
0213 ilf->ilf_size++;
0214 } else {
0215 iip->ili_fields &= ~XFS_ILOG_DDATA;
0216 }
0217 break;
0218 case XFS_DINODE_FMT_DEV:
0219 iip->ili_fields &=
0220 ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | XFS_ILOG_DEXT);
0221 if (iip->ili_fields & XFS_ILOG_DEV)
0222 ilf->ilf_u.ilfu_rdev = sysv_encode_dev(VFS_I(ip)->i_rdev);
0223 break;
0224 default:
0225 ASSERT(0);
0226 break;
0227 }
0228 }
0229
0230 STATIC void
0231 xfs_inode_item_format_attr_fork(
0232 struct xfs_inode_log_item *iip,
0233 struct xfs_inode_log_format *ilf,
0234 struct xfs_log_vec *lv,
0235 struct xfs_log_iovec **vecp)
0236 {
0237 struct xfs_inode *ip = iip->ili_inode;
0238 size_t data_bytes;
0239
0240 switch (ip->i_af.if_format) {
0241 case XFS_DINODE_FMT_EXTENTS:
0242 iip->ili_fields &=
0243 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
0244
0245 if ((iip->ili_fields & XFS_ILOG_AEXT) &&
0246 ip->i_af.if_nextents > 0 &&
0247 ip->i_af.if_bytes > 0) {
0248 struct xfs_bmbt_rec *p;
0249
0250 ASSERT(xfs_iext_count(&ip->i_af) ==
0251 ip->i_af.if_nextents);
0252
0253 p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT);
0254 data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK);
0255 xlog_finish_iovec(lv, *vecp, data_bytes);
0256
0257 ilf->ilf_asize = data_bytes;
0258 ilf->ilf_size++;
0259 } else {
0260 iip->ili_fields &= ~XFS_ILOG_AEXT;
0261 }
0262 break;
0263 case XFS_DINODE_FMT_BTREE:
0264 iip->ili_fields &=
0265 ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT);
0266
0267 if ((iip->ili_fields & XFS_ILOG_ABROOT) &&
0268 ip->i_af.if_broot_bytes > 0) {
0269 ASSERT(ip->i_af.if_broot != NULL);
0270
0271 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_BROOT,
0272 ip->i_af.if_broot,
0273 ip->i_af.if_broot_bytes);
0274 ilf->ilf_asize = ip->i_af.if_broot_bytes;
0275 ilf->ilf_size++;
0276 } else {
0277 iip->ili_fields &= ~XFS_ILOG_ABROOT;
0278 }
0279 break;
0280 case XFS_DINODE_FMT_LOCAL:
0281 iip->ili_fields &=
0282 ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT);
0283
0284 if ((iip->ili_fields & XFS_ILOG_ADATA) &&
0285 ip->i_af.if_bytes > 0) {
0286 ASSERT(ip->i_af.if_u1.if_data != NULL);
0287 xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL,
0288 ip->i_af.if_u1.if_data,
0289 ip->i_af.if_bytes);
0290 ilf->ilf_asize = (unsigned)ip->i_af.if_bytes;
0291 ilf->ilf_size++;
0292 } else {
0293 iip->ili_fields &= ~XFS_ILOG_ADATA;
0294 }
0295 break;
0296 default:
0297 ASSERT(0);
0298 break;
0299 }
0300 }
0301
0302
0303
0304
0305
0306 static inline xfs_log_timestamp_t
0307 xfs_inode_to_log_dinode_ts(
0308 struct xfs_inode *ip,
0309 const struct timespec64 tv)
0310 {
0311 struct xfs_log_legacy_timestamp *lits;
0312 xfs_log_timestamp_t its;
0313
0314 if (xfs_inode_has_bigtime(ip))
0315 return xfs_inode_encode_bigtime(tv);
0316
0317 lits = (struct xfs_log_legacy_timestamp *)&its;
0318 lits->t_sec = tv.tv_sec;
0319 lits->t_nsec = tv.tv_nsec;
0320
0321 return its;
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 static void
0333 xfs_copy_dm_fields_to_log_dinode(
0334 struct xfs_inode *ip,
0335 struct xfs_log_dinode *to)
0336 {
0337 struct xfs_dinode *dip;
0338
0339 dip = xfs_buf_offset(ip->i_itemp->ili_item.li_buf,
0340 ip->i_imap.im_boffset);
0341
0342 if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS)) {
0343 to->di_dmevmask = be32_to_cpu(dip->di_dmevmask);
0344 to->di_dmstate = be16_to_cpu(dip->di_dmstate);
0345 } else {
0346 to->di_dmevmask = 0;
0347 to->di_dmstate = 0;
0348 }
0349 }
0350
0351 static inline void
0352 xfs_inode_to_log_dinode_iext_counters(
0353 struct xfs_inode *ip,
0354 struct xfs_log_dinode *to)
0355 {
0356 if (xfs_inode_has_large_extent_counts(ip)) {
0357 to->di_big_nextents = xfs_ifork_nextents(&ip->i_df);
0358 to->di_big_anextents = xfs_ifork_nextents(&ip->i_af);
0359 to->di_nrext64_pad = 0;
0360 } else {
0361 to->di_nextents = xfs_ifork_nextents(&ip->i_df);
0362 to->di_anextents = xfs_ifork_nextents(&ip->i_af);
0363 }
0364 }
0365
0366 static void
0367 xfs_inode_to_log_dinode(
0368 struct xfs_inode *ip,
0369 struct xfs_log_dinode *to,
0370 xfs_lsn_t lsn)
0371 {
0372 struct inode *inode = VFS_I(ip);
0373
0374 to->di_magic = XFS_DINODE_MAGIC;
0375 to->di_format = xfs_ifork_format(&ip->i_df);
0376 to->di_uid = i_uid_read(inode);
0377 to->di_gid = i_gid_read(inode);
0378 to->di_projid_lo = ip->i_projid & 0xffff;
0379 to->di_projid_hi = ip->i_projid >> 16;
0380
0381 memset(to->di_pad3, 0, sizeof(to->di_pad3));
0382 to->di_atime = xfs_inode_to_log_dinode_ts(ip, inode->i_atime);
0383 to->di_mtime = xfs_inode_to_log_dinode_ts(ip, inode->i_mtime);
0384 to->di_ctime = xfs_inode_to_log_dinode_ts(ip, inode->i_ctime);
0385 to->di_nlink = inode->i_nlink;
0386 to->di_gen = inode->i_generation;
0387 to->di_mode = inode->i_mode;
0388
0389 to->di_size = ip->i_disk_size;
0390 to->di_nblocks = ip->i_nblocks;
0391 to->di_extsize = ip->i_extsize;
0392 to->di_forkoff = ip->i_forkoff;
0393 to->di_aformat = xfs_ifork_format(&ip->i_af);
0394 to->di_flags = ip->i_diflags;
0395
0396 xfs_copy_dm_fields_to_log_dinode(ip, to);
0397
0398
0399 to->di_next_unlinked = NULLAGINO;
0400
0401 if (xfs_has_v3inodes(ip->i_mount)) {
0402 to->di_version = 3;
0403 to->di_changecount = inode_peek_iversion(inode);
0404 to->di_crtime = xfs_inode_to_log_dinode_ts(ip, ip->i_crtime);
0405 to->di_flags2 = ip->i_diflags2;
0406 to->di_cowextsize = ip->i_cowextsize;
0407 to->di_ino = ip->i_ino;
0408 to->di_lsn = lsn;
0409 memset(to->di_pad2, 0, sizeof(to->di_pad2));
0410 uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
0411 to->di_v3_pad = 0;
0412 } else {
0413 to->di_version = 2;
0414 to->di_flushiter = ip->i_flushiter;
0415 memset(to->di_v2_pad, 0, sizeof(to->di_v2_pad));
0416 }
0417
0418 xfs_inode_to_log_dinode_iext_counters(ip, to);
0419 }
0420
0421
0422
0423
0424
0425
0426 static void
0427 xfs_inode_item_format_core(
0428 struct xfs_inode *ip,
0429 struct xfs_log_vec *lv,
0430 struct xfs_log_iovec **vecp)
0431 {
0432 struct xfs_log_dinode *dic;
0433
0434 dic = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_ICORE);
0435 xfs_inode_to_log_dinode(ip, dic, ip->i_itemp->ili_item.li_lsn);
0436 xlog_finish_iovec(lv, *vecp, xfs_log_dinode_size(ip->i_mount));
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451 STATIC void
0452 xfs_inode_item_format(
0453 struct xfs_log_item *lip,
0454 struct xfs_log_vec *lv)
0455 {
0456 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0457 struct xfs_inode *ip = iip->ili_inode;
0458 struct xfs_log_iovec *vecp = NULL;
0459 struct xfs_inode_log_format *ilf;
0460
0461 ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT);
0462 ilf->ilf_type = XFS_LI_INODE;
0463 ilf->ilf_ino = ip->i_ino;
0464 ilf->ilf_blkno = ip->i_imap.im_blkno;
0465 ilf->ilf_len = ip->i_imap.im_len;
0466 ilf->ilf_boffset = ip->i_imap.im_boffset;
0467 ilf->ilf_fields = XFS_ILOG_CORE;
0468 ilf->ilf_size = 2;
0469
0470
0471
0472
0473
0474 ilf->ilf_dsize = 0;
0475 ilf->ilf_asize = 0;
0476 ilf->ilf_pad = 0;
0477 memset(&ilf->ilf_u, 0, sizeof(ilf->ilf_u));
0478
0479 xlog_finish_iovec(lv, vecp, sizeof(*ilf));
0480
0481 xfs_inode_item_format_core(ip, lv, &vecp);
0482 xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp);
0483 if (xfs_inode_has_attr_fork(ip)) {
0484 xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp);
0485 } else {
0486 iip->ili_fields &=
0487 ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT);
0488 }
0489
0490
0491 ilf->ilf_fields |= (iip->ili_fields & ~XFS_ILOG_TIMESTAMP);
0492 }
0493
0494
0495
0496
0497
0498 STATIC void
0499 xfs_inode_item_pin(
0500 struct xfs_log_item *lip)
0501 {
0502 struct xfs_inode *ip = INODE_ITEM(lip)->ili_inode;
0503
0504 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
0505 ASSERT(lip->li_buf);
0506
0507 trace_xfs_inode_pin(ip, _RET_IP_);
0508 atomic_inc(&ip->i_pincount);
0509 }
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 STATIC void
0525 xfs_inode_item_unpin(
0526 struct xfs_log_item *lip,
0527 int remove)
0528 {
0529 struct xfs_inode *ip = INODE_ITEM(lip)->ili_inode;
0530
0531 trace_xfs_inode_unpin(ip, _RET_IP_);
0532 ASSERT(lip->li_buf || xfs_iflags_test(ip, XFS_ISTALE));
0533 ASSERT(atomic_read(&ip->i_pincount) > 0);
0534 if (atomic_dec_and_test(&ip->i_pincount))
0535 wake_up_bit(&ip->i_flags, __XFS_IPINNED_BIT);
0536 }
0537
0538 STATIC uint
0539 xfs_inode_item_push(
0540 struct xfs_log_item *lip,
0541 struct list_head *buffer_list)
0542 __releases(&lip->li_ailp->ail_lock)
0543 __acquires(&lip->li_ailp->ail_lock)
0544 {
0545 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0546 struct xfs_inode *ip = iip->ili_inode;
0547 struct xfs_buf *bp = lip->li_buf;
0548 uint rval = XFS_ITEM_SUCCESS;
0549 int error;
0550
0551 if (!bp || (ip->i_flags & XFS_ISTALE)) {
0552
0553
0554
0555
0556
0557
0558 return XFS_ITEM_PINNED;
0559 }
0560
0561 if (xfs_ipincount(ip) > 0 || xfs_buf_ispinned(bp))
0562 return XFS_ITEM_PINNED;
0563
0564 if (xfs_iflags_test(ip, XFS_IFLUSHING))
0565 return XFS_ITEM_FLUSHING;
0566
0567 if (!xfs_buf_trylock(bp))
0568 return XFS_ITEM_LOCKED;
0569
0570 spin_unlock(&lip->li_ailp->ail_lock);
0571
0572
0573
0574
0575
0576
0577
0578 xfs_buf_hold(bp);
0579 error = xfs_iflush_cluster(bp);
0580 if (!error) {
0581 if (!xfs_buf_delwri_queue(bp, buffer_list))
0582 rval = XFS_ITEM_FLUSHING;
0583 xfs_buf_relse(bp);
0584 } else {
0585
0586
0587
0588
0589 if (error == -EAGAIN)
0590 xfs_buf_relse(bp);
0591 rval = XFS_ITEM_LOCKED;
0592 }
0593
0594 spin_lock(&lip->li_ailp->ail_lock);
0595 return rval;
0596 }
0597
0598
0599
0600
0601 STATIC void
0602 xfs_inode_item_release(
0603 struct xfs_log_item *lip)
0604 {
0605 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0606 struct xfs_inode *ip = iip->ili_inode;
0607 unsigned short lock_flags;
0608
0609 ASSERT(ip->i_itemp != NULL);
0610 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
0611
0612 lock_flags = iip->ili_lock_flags;
0613 iip->ili_lock_flags = 0;
0614 if (lock_flags)
0615 xfs_iunlock(ip, lock_flags);
0616 }
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640 STATIC xfs_lsn_t
0641 xfs_inode_item_committed(
0642 struct xfs_log_item *lip,
0643 xfs_lsn_t lsn)
0644 {
0645 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0646 struct xfs_inode *ip = iip->ili_inode;
0647
0648 if (xfs_iflags_test(ip, XFS_ISTALE)) {
0649 xfs_inode_item_unpin(lip, 0);
0650 return -1;
0651 }
0652 return lsn;
0653 }
0654
0655 STATIC void
0656 xfs_inode_item_committing(
0657 struct xfs_log_item *lip,
0658 xfs_csn_t seq)
0659 {
0660 INODE_ITEM(lip)->ili_commit_seq = seq;
0661 return xfs_inode_item_release(lip);
0662 }
0663
0664 static const struct xfs_item_ops xfs_inode_item_ops = {
0665 .iop_size = xfs_inode_item_size,
0666 .iop_format = xfs_inode_item_format,
0667 .iop_pin = xfs_inode_item_pin,
0668 .iop_unpin = xfs_inode_item_unpin,
0669 .iop_release = xfs_inode_item_release,
0670 .iop_committed = xfs_inode_item_committed,
0671 .iop_push = xfs_inode_item_push,
0672 .iop_committing = xfs_inode_item_committing,
0673 };
0674
0675
0676
0677
0678
0679 void
0680 xfs_inode_item_init(
0681 struct xfs_inode *ip,
0682 struct xfs_mount *mp)
0683 {
0684 struct xfs_inode_log_item *iip;
0685
0686 ASSERT(ip->i_itemp == NULL);
0687 iip = ip->i_itemp = kmem_cache_zalloc(xfs_ili_cache,
0688 GFP_KERNEL | __GFP_NOFAIL);
0689
0690 iip->ili_inode = ip;
0691 spin_lock_init(&iip->ili_lock);
0692 xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE,
0693 &xfs_inode_item_ops);
0694 }
0695
0696
0697
0698
0699 void
0700 xfs_inode_item_destroy(
0701 struct xfs_inode *ip)
0702 {
0703 struct xfs_inode_log_item *iip = ip->i_itemp;
0704
0705 ASSERT(iip->ili_item.li_buf == NULL);
0706
0707 ip->i_itemp = NULL;
0708 kmem_free(iip->ili_item.li_lv_shadow);
0709 kmem_cache_free(xfs_ili_cache, iip);
0710 }
0711
0712
0713
0714
0715
0716
0717
0718 static void
0719 xfs_iflush_ail_updates(
0720 struct xfs_ail *ailp,
0721 struct list_head *list)
0722 {
0723 struct xfs_log_item *lip;
0724 xfs_lsn_t tail_lsn = 0;
0725
0726
0727 spin_lock(&ailp->ail_lock);
0728 list_for_each_entry(lip, list, li_bio_list) {
0729 xfs_lsn_t lsn;
0730
0731 clear_bit(XFS_LI_FAILED, &lip->li_flags);
0732 if (INODE_ITEM(lip)->ili_flush_lsn != lip->li_lsn)
0733 continue;
0734
0735
0736
0737
0738
0739
0740
0741 if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
0742 ASSERT(xlog_is_shutdown(lip->li_log));
0743 continue;
0744 }
0745
0746 lsn = xfs_ail_delete_one(ailp, lip);
0747 if (!tail_lsn && lsn)
0748 tail_lsn = lsn;
0749 }
0750 xfs_ail_update_finish(ailp, tail_lsn);
0751 }
0752
0753
0754
0755
0756
0757
0758
0759 static void
0760 xfs_iflush_finish(
0761 struct xfs_buf *bp,
0762 struct list_head *list)
0763 {
0764 struct xfs_log_item *lip, *n;
0765
0766 list_for_each_entry_safe(lip, n, list, li_bio_list) {
0767 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0768 bool drop_buffer = false;
0769
0770 spin_lock(&iip->ili_lock);
0771
0772
0773
0774
0775
0776
0777 ASSERT(iip->ili_item.li_buf == bp);
0778 if (!iip->ili_fields) {
0779 iip->ili_item.li_buf = NULL;
0780 list_del_init(&lip->li_bio_list);
0781 drop_buffer = true;
0782 }
0783 iip->ili_last_fields = 0;
0784 iip->ili_flush_lsn = 0;
0785 spin_unlock(&iip->ili_lock);
0786 xfs_iflags_clear(iip->ili_inode, XFS_IFLUSHING);
0787 if (drop_buffer)
0788 xfs_buf_rele(bp);
0789 }
0790 }
0791
0792
0793
0794
0795
0796
0797 void
0798 xfs_buf_inode_iodone(
0799 struct xfs_buf *bp)
0800 {
0801 struct xfs_log_item *lip, *n;
0802 LIST_HEAD(flushed_inodes);
0803 LIST_HEAD(ail_updates);
0804
0805
0806
0807
0808
0809 list_for_each_entry_safe(lip, n, &bp->b_li_list, li_bio_list) {
0810 struct xfs_inode_log_item *iip = INODE_ITEM(lip);
0811
0812 if (xfs_iflags_test(iip->ili_inode, XFS_ISTALE)) {
0813 xfs_iflush_abort(iip->ili_inode);
0814 continue;
0815 }
0816 if (!iip->ili_last_fields)
0817 continue;
0818
0819
0820 if (iip->ili_flush_lsn == lip->li_lsn ||
0821 test_bit(XFS_LI_FAILED, &lip->li_flags))
0822 list_move_tail(&lip->li_bio_list, &ail_updates);
0823 else
0824 list_move_tail(&lip->li_bio_list, &flushed_inodes);
0825 }
0826
0827 if (!list_empty(&ail_updates)) {
0828 xfs_iflush_ail_updates(bp->b_mount->m_ail, &ail_updates);
0829 list_splice_tail(&ail_updates, &flushed_inodes);
0830 }
0831
0832 xfs_iflush_finish(bp, &flushed_inodes);
0833 if (!list_empty(&flushed_inodes))
0834 list_splice_tail(&flushed_inodes, &bp->b_li_list);
0835 }
0836
0837 void
0838 xfs_buf_inode_io_fail(
0839 struct xfs_buf *bp)
0840 {
0841 struct xfs_log_item *lip;
0842
0843 list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
0844 set_bit(XFS_LI_FAILED, &lip->li_flags);
0845 }
0846
0847
0848
0849
0850
0851
0852
0853 static void
0854 xfs_iflush_abort_clean(
0855 struct xfs_inode_log_item *iip)
0856 {
0857 iip->ili_last_fields = 0;
0858 iip->ili_fields = 0;
0859 iip->ili_fsync_fields = 0;
0860 iip->ili_flush_lsn = 0;
0861 iip->ili_item.li_buf = NULL;
0862 list_del_init(&iip->ili_item.li_bio_list);
0863 }
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877 void
0878 xfs_iflush_abort(
0879 struct xfs_inode *ip)
0880 {
0881 struct xfs_inode_log_item *iip = ip->i_itemp;
0882 struct xfs_buf *bp;
0883
0884 if (!iip) {
0885
0886 xfs_iflags_clear(ip, XFS_IFLUSHING);
0887 return;
0888 }
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901 clear_bit(XFS_LI_FAILED, &iip->ili_item.li_flags);
0902 xfs_trans_ail_delete(&iip->ili_item, 0);
0903
0904
0905
0906
0907
0908 spin_lock(&iip->ili_lock);
0909 bp = iip->ili_item.li_buf;
0910 xfs_iflush_abort_clean(iip);
0911 spin_unlock(&iip->ili_lock);
0912
0913 xfs_iflags_clear(ip, XFS_IFLUSHING);
0914 if (bp)
0915 xfs_buf_rele(bp);
0916 }
0917
0918
0919
0920
0921
0922
0923
0924 void
0925 xfs_iflush_shutdown_abort(
0926 struct xfs_inode *ip)
0927 {
0928 struct xfs_inode_log_item *iip = ip->i_itemp;
0929 struct xfs_buf *bp;
0930
0931 if (!iip) {
0932
0933 xfs_iflags_clear(ip, XFS_IFLUSHING);
0934 return;
0935 }
0936
0937 spin_lock(&iip->ili_lock);
0938 bp = iip->ili_item.li_buf;
0939 if (!bp) {
0940 spin_unlock(&iip->ili_lock);
0941 xfs_iflush_abort(ip);
0942 return;
0943 }
0944
0945
0946
0947
0948
0949
0950
0951 xfs_buf_hold(bp);
0952 spin_unlock(&iip->ili_lock);
0953 xfs_buf_lock(bp);
0954
0955 spin_lock(&iip->ili_lock);
0956 if (!iip->ili_item.li_buf) {
0957
0958
0959
0960
0961
0962 ASSERT(list_empty(&iip->ili_item.li_bio_list));
0963 ASSERT(!test_bit(XFS_LI_IN_AIL, &iip->ili_item.li_flags));
0964 xfs_iflush_abort_clean(iip);
0965 spin_unlock(&iip->ili_lock);
0966 xfs_iflags_clear(ip, XFS_IFLUSHING);
0967 xfs_buf_relse(bp);
0968 return;
0969 }
0970
0971
0972
0973
0974
0975
0976
0977
0978 ASSERT(iip->ili_item.li_buf == bp);
0979 spin_unlock(&iip->ili_lock);
0980 xfs_iflush_abort(ip);
0981 xfs_buf_relse(bp);
0982 }
0983
0984
0985
0986
0987
0988
0989 int
0990 xfs_inode_item_format_convert(
0991 struct xfs_log_iovec *buf,
0992 struct xfs_inode_log_format *in_f)
0993 {
0994 struct xfs_inode_log_format_32 *in_f32 = buf->i_addr;
0995
0996 if (buf->i_len != sizeof(*in_f32)) {
0997 XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
0998 return -EFSCORRUPTED;
0999 }
1000
1001 in_f->ilf_type = in_f32->ilf_type;
1002 in_f->ilf_size = in_f32->ilf_size;
1003 in_f->ilf_fields = in_f32->ilf_fields;
1004 in_f->ilf_asize = in_f32->ilf_asize;
1005 in_f->ilf_dsize = in_f32->ilf_dsize;
1006 in_f->ilf_ino = in_f32->ilf_ino;
1007 memcpy(&in_f->ilf_u, &in_f32->ilf_u, sizeof(in_f->ilf_u));
1008 in_f->ilf_blkno = in_f32->ilf_blkno;
1009 in_f->ilf_len = in_f32->ilf_len;
1010 in_f->ilf_boffset = in_f32->ilf_boffset;
1011 return 0;
1012 }