📄 xfs_inode_item.c
字号:
XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IBROOT); vecp++; nvecs++; iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; } break; case XFS_DINODE_FMT_LOCAL: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_DBROOT | XFS_ILOG_DEXT | XFS_ILOG_DEV | XFS_ILOG_UUID))); if (iip->ili_format.ilf_fields & XFS_ILOG_DDATA) { ASSERT(ip->i_df.if_bytes > 0); ASSERT(ip->i_df.if_u1.if_data != NULL); ASSERT(ip->i_d.di_size > 0); vecp->i_addr = (xfs_caddr_t)ip->i_df.if_u1.if_data; /* * Round i_bytes up to a word boundary. * The underlying memory is guaranteed to * to be there by xfs_idata_realloc(). */ data_bytes = roundup(ip->i_df.if_bytes, 4); ASSERT((ip->i_df.if_real_bytes == 0) || (ip->i_df.if_real_bytes == data_bytes)); vecp->i_len = (int)data_bytes; XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ILOCAL); vecp++; nvecs++; iip->ili_format.ilf_dsize = (unsigned)data_bytes; } break; case XFS_DINODE_FMT_DEV: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_DBROOT | XFS_ILOG_DEXT | XFS_ILOG_DDATA | XFS_ILOG_UUID))); if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) { iip->ili_format.ilf_u.ilfu_rdev = ip->i_df.if_u2.if_rdev; } break; case XFS_DINODE_FMT_UUID: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_DBROOT | XFS_ILOG_DEXT | XFS_ILOG_DDATA | XFS_ILOG_DEV))); if (iip->ili_format.ilf_fields & XFS_ILOG_UUID) { iip->ili_format.ilf_u.ilfu_uuid = ip->i_df.if_u2.if_uuid; } break; default: ASSERT(0); break; } /* * If there are no attributes associated with the file, * then we're done. * Assert that no attribute-related log flags are set. */ if (!XFS_IFORK_Q(ip)) { ASSERT(nvecs == iip->ili_item.li_desc->lid_size); iip->ili_format.ilf_size = nvecs; ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT))); return; } switch (ip->i_d.di_aformat) { case XFS_DINODE_FMT_EXTENTS: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_ADATA | XFS_ILOG_ABROOT))); if (iip->ili_format.ilf_fields & XFS_ILOG_AEXT) { ASSERT(ip->i_afp->if_bytes > 0); ASSERT(ip->i_afp->if_u1.if_extents != NULL); ASSERT(ip->i_d.di_anextents > 0);#ifdef DEBUG nrecs = ip->i_afp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);#endif ASSERT(nrecs > 0); ASSERT(nrecs == ip->i_d.di_anextents);#ifdef XFS_NATIVE_HOST /* * There are not delayed allocation extents * for attributes, so just point at the array. */ vecp->i_addr = (char *)(ip->i_afp->if_u1.if_extents); vecp->i_len = ip->i_afp->if_bytes;#else ASSERT(iip->ili_aextents_buf == NULL); /* * Need to endian flip before logging */ ext_buffer = kmem_alloc(ip->i_afp->if_bytes, KM_SLEEP); iip->ili_aextents_buf = ext_buffer; vecp->i_addr = (xfs_caddr_t)ext_buffer; vecp->i_len = xfs_iextents_copy(ip, ext_buffer, XFS_ATTR_FORK);#endif XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_EXT); iip->ili_format.ilf_asize = vecp->i_len; vecp++; nvecs++; } break; case XFS_DINODE_FMT_BTREE: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_ADATA | XFS_ILOG_AEXT))); if (iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) { ASSERT(ip->i_afp->if_broot_bytes > 0); ASSERT(ip->i_afp->if_broot != NULL); vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot; vecp->i_len = ip->i_afp->if_broot_bytes; XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_BROOT); vecp++; nvecs++; iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; } break; case XFS_DINODE_FMT_LOCAL: ASSERT(!(iip->ili_format.ilf_fields & (XFS_ILOG_ABROOT | XFS_ILOG_AEXT))); if (iip->ili_format.ilf_fields & XFS_ILOG_ADATA) { ASSERT(ip->i_afp->if_bytes > 0); ASSERT(ip->i_afp->if_u1.if_data != NULL); vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_u1.if_data; /* * Round i_bytes up to a word boundary. * The underlying memory is guaranteed to * to be there by xfs_idata_realloc(). */ data_bytes = roundup(ip->i_afp->if_bytes, 4); ASSERT((ip->i_afp->if_real_bytes == 0) || (ip->i_afp->if_real_bytes == data_bytes)); vecp->i_len = (int)data_bytes; XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_LOCAL); vecp++; nvecs++; iip->ili_format.ilf_asize = (unsigned)data_bytes; } break; default: ASSERT(0); break; } ASSERT(nvecs == iip->ili_item.li_desc->lid_size); iip->ili_format.ilf_size = nvecs;}/* * This is called to pin the inode associated with the inode log * item in memory so it cannot be written out. Do this by calling * xfs_ipin() to bump the pin count in the inode while holding the * inode pin lock. */STATIC voidxfs_inode_item_pin( xfs_inode_log_item_t *iip){ ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE)); xfs_ipin(iip->ili_inode);}/* * This is called to unpin the inode associated with the inode log * item which was previously pinned with a call to xfs_inode_item_pin(). * Just call xfs_iunpin() on the inode to do this. *//* ARGSUSED */STATIC voidxfs_inode_item_unpin( xfs_inode_log_item_t *iip, int stale){ xfs_iunpin(iip->ili_inode);}/* ARGSUSED */STATIC voidxfs_inode_item_unpin_remove( xfs_inode_log_item_t *iip, xfs_trans_t *tp){ xfs_iunpin(iip->ili_inode);}/* * This is called to attempt to lock the inode associated with this * inode log item, in preparation for the push routine which does the actual * iflush. Don't sleep on the inode lock or the flush lock. * * If the flush lock is already held, indicating that the inode has * been or is in the process of being flushed, then (ideally) we'd like to * see if the inode's buffer is still incore, and if so give it a nudge. * We delay doing so until the pushbuf routine, though, to avoid holding * the AIL lock across a call to the blackhole which is the buffer cache. * Also we don't want to sleep in any device strategy routines, which can happen * if we do the subsequent bawrite in here. */STATIC uintxfs_inode_item_trylock( xfs_inode_log_item_t *iip){ register xfs_inode_t *ip; ip = iip->ili_inode; if (xfs_ipincount(ip) > 0) { return XFS_ITEM_PINNED; } if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { return XFS_ITEM_LOCKED; } if (!xfs_iflock_nowait(ip)) { /* * If someone else isn't already trying to push the inode * buffer, we get to do it. */ if (iip->ili_pushbuf_flag == 0) { iip->ili_pushbuf_flag = 1;#ifdef DEBUG iip->ili_push_owner = current_pid();#endif /* * Inode is left locked in shared mode. * Pushbuf routine gets to unlock it. */ return XFS_ITEM_PUSHBUF; } else { /* * We hold the AIL_LOCK, so we must specify the * NONOTIFY flag so that we won't double trip. */ xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY); return XFS_ITEM_FLUSHING; } /* NOTREACHED */ } /* Stale items should force out the iclog */ if (ip->i_flags & XFS_ISTALE) { xfs_ifunlock(ip); xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY); return XFS_ITEM_PINNED; }#ifdef DEBUG if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { ASSERT(iip->ili_format.ilf_fields != 0); ASSERT(iip->ili_logged == 0); ASSERT(iip->ili_item.li_flags & XFS_LI_IN_AIL); }#endif return XFS_ITEM_SUCCESS;}/* * Unlock the inode associated with the inode log item. * Clear the fields of the inode and inode log item that * are specific to the current transaction. If the * hold flags is set, do not unlock the inode. */STATIC voidxfs_inode_item_unlock( xfs_inode_log_item_t *iip){ uint hold; uint iolocked; uint lock_flags; xfs_inode_t *ip; ASSERT(iip != NULL); ASSERT(iip->ili_inode->i_itemp != NULL); ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE)); ASSERT((!(iip->ili_inode->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL)) || ismrlocked(&(iip->ili_inode->i_iolock), MR_UPDATE)); ASSERT((!(iip->ili_inode->i_itemp->ili_flags & XFS_ILI_IOLOCKED_SHARED)) || ismrlocked(&(iip->ili_inode->i_iolock), MR_ACCESS)); /* * Clear the transaction pointer in the inode. */ ip = iip->ili_inode; ip->i_transp = NULL; /* * If the inode needed a separate buffer with which to log * its extents, then free it now. */ if (iip->ili_extents_buf != NULL) { ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS); ASSERT(ip->i_d.di_nextents > 0); ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_DEXT); ASSERT(ip->i_df.if_bytes > 0); kmem_free(iip->ili_extents_buf, ip->i_df.if_bytes); iip->ili_extents_buf = NULL; } if (iip->ili_aextents_buf != NULL) { ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS); ASSERT(ip->i_d.di_anextents > 0); ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_AEXT); ASSERT(ip->i_afp->if_bytes > 0); kmem_free(iip->ili_aextents_buf, ip->i_afp->if_bytes); iip->ili_aextents_buf = NULL; } /* * Figure out if we should unlock the inode or not. */ hold = iip->ili_flags & XFS_ILI_HOLD; /* * Before clearing out the flags, remember whether we * are holding the inode's IO lock. */ iolocked = iip->ili_flags & XFS_ILI_IOLOCKED_ANY; /* * Clear out the fields of the inode log item particular * to the current transaction. */ iip->ili_ilock_recur = 0; iip->ili_iolock_recur = 0; iip->ili_flags = 0; /* * Unlock the inode if XFS_ILI_HOLD was not set. */ if (!hold) { lock_flags = XFS_ILOCK_EXCL; if (iolocked & XFS_ILI_IOLOCKED_EXCL) { lock_flags |= XFS_IOLOCK_EXCL; } else if (iolocked & XFS_ILI_IOLOCKED_SHARED) { lock_flags |= XFS_IOLOCK_SHARED; } xfs_iput(iip->ili_inode, lock_flags); }}/* * This is called to find out where the oldest active copy of the * inode log item in the on disk log resides now that the last log * write of it completed at the given lsn. Since we always re-log * all dirty data in an inode, the latest copy in the on disk log * is the only one that matters. Therefore, simply return the * given lsn. *//*ARGSUSED*/STATIC xfs_lsn_txfs_inode_item_committed( xfs_inode_log_item_t *iip, xfs_lsn_t lsn){ return (lsn);}/* * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -