summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_inode_item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_inode_item.c')
-rw-r--r--fs/xfs/xfs_inode_item.c128
1 files changed, 123 insertions, 5 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index d14b12b8cfef..3ad997278869 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -135,7 +135,7 @@ xfs_inode_item_size(
*nvecs += 2;
*nbytes += sizeof(struct xfs_inode_log_format) +
- xfs_icdinode_size(ip->i_d.di_version);
+ xfs_log_dinode_size(ip->i_d.di_version);
xfs_inode_item_data_fork_size(iip, nvecs, nbytes);
if (XFS_IFORK_Q(ip))
@@ -322,6 +322,127 @@ xfs_inode_item_format_attr_fork(
}
}
+static void
+xfs_icdinode_to_log_dinode(
+ struct xfs_icdinode *from,
+ struct xfs_log_dinode *to)
+{
+ to->di_magic = from->di_magic;
+ to->di_mode = from->di_mode;
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+ to->di_onlink = from->di_onlink;
+ to->di_uid = from->di_uid;
+ to->di_gid = from->di_gid;
+ to->di_nlink = from->di_nlink;
+ to->di_projid_lo = from->di_projid_lo;
+ to->di_projid_hi = from->di_projid_hi;
+ memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
+ to->di_atime.t_sec = from->di_atime.t_sec;
+ to->di_atime.t_nsec = from->di_atime.t_nsec;
+ to->di_mtime.t_sec = from->di_mtime.t_sec;
+ to->di_mtime.t_nsec = from->di_mtime.t_nsec;
+ to->di_ctime.t_sec = from->di_ctime.t_sec;
+ to->di_ctime.t_nsec = from->di_ctime.t_nsec;
+ to->di_size = from->di_size;
+ to->di_nblocks = from->di_nblocks;
+ to->di_extsize = from->di_extsize;
+ to->di_nextents = from->di_nextents;
+ to->di_anextents = from->di_anextents;
+ to->di_forkoff = from->di_forkoff;
+ to->di_aformat = from->di_aformat;
+ to->di_dmevmask = from->di_dmevmask;
+ to->di_dmstate = from->di_dmstate;
+ to->di_flags = from->di_flags;
+ to->di_gen = from->di_gen;
+
+ if (from->di_version == 3) {
+ to->di_changecount = from->di_changecount;
+ to->di_crtime.t_sec = from->di_crtime.t_sec;
+ to->di_crtime.t_nsec = from->di_crtime.t_nsec;
+ to->di_flags2 = from->di_flags2;
+ to->di_ino = from->di_ino;
+ to->di_lsn = from->di_lsn;
+ memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
+ uuid_copy(&to->di_uuid, &from->di_uuid);
+ to->di_flushiter = 0;
+ } else {
+ to->di_flushiter = from->di_flushiter;
+ }
+}
+
+/*
+ * Recovery needs to be able to convert a log dinode back to a real dinode
+ * for writeback we do that by converting a log dinode to a icdinode, and
+ * then passing that to the formatting function.
+ */
+void
+xfs_log_dinode_to_icdinode(
+ struct xfs_log_dinode *from,
+ struct xfs_icdinode *to)
+{
+ to->di_magic = from->di_magic;
+ to->di_mode = from->di_mode;
+ to->di_version = from->di_version;
+ to->di_format = from->di_format;
+ to->di_onlink = from->di_onlink;
+ to->di_uid = from->di_uid;
+ to->di_gid = from->di_gid;
+ to->di_nlink = from->di_nlink;
+ to->di_projid_lo = from->di_projid_lo;
+ to->di_projid_hi = from->di_projid_hi;
+ memset(to->di_pad, 0, sizeof(to->di_pad));
+ to->di_atime.t_sec = from->di_atime.t_sec;
+ to->di_atime.t_nsec = from->di_atime.t_nsec;
+ to->di_mtime.t_sec = from->di_mtime.t_sec;
+ to->di_mtime.t_nsec = from->di_mtime.t_nsec;
+ to->di_ctime.t_sec = from->di_ctime.t_sec;
+ to->di_ctime.t_nsec = from->di_ctime.t_nsec;
+ to->di_size = from->di_size;
+ to->di_nblocks = from->di_nblocks;
+ to->di_extsize = from->di_extsize;
+ to->di_nextents = from->di_nextents;
+ to->di_anextents = from->di_anextents;
+ to->di_forkoff = from->di_forkoff;
+ to->di_aformat = from->di_aformat;
+ to->di_dmevmask = from->di_dmevmask;
+ to->di_dmstate = from->di_dmstate;
+ to->di_flags = from->di_flags;
+ to->di_gen = from->di_gen;
+
+ if (from->di_version == 3) {
+ to->di_changecount = from->di_changecount;
+ to->di_crtime.t_sec = from->di_crtime.t_sec;
+ to->di_crtime.t_nsec = from->di_crtime.t_nsec;
+ to->di_flags2 = from->di_flags2;
+ to->di_ino = from->di_ino;
+ to->di_lsn = from->di_lsn;
+ memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
+ uuid_copy(&to->di_uuid, &from->di_uuid);
+ to->di_flushiter = 0;
+ } else {
+ to->di_flushiter = from->di_flushiter;
+ }
+}
+
+/*
+ * Format the inode core. Current timestamp data is only in the VFS inode
+ * fields, so we need to grab them from there. Hence rather than just copying
+ * the XFS inode core structure, format the fields directly into the iovec.
+ */
+static void
+xfs_inode_item_format_core(
+ struct xfs_inode *ip,
+ struct xfs_log_vec *lv,
+ struct xfs_log_iovec **vecp)
+{
+ struct xfs_log_dinode *dic;
+
+ dic = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_ICORE);
+ xfs_icdinode_to_log_dinode(&ip->i_d, dic);
+ xlog_finish_iovec(lv, *vecp, xfs_log_dinode_size(ip->i_d.di_version));
+}
+
/*
* This is called to fill in the vector of log iovecs for the given inode
* log item. It fills the first item with an inode log format structure,
@@ -351,10 +472,7 @@ xfs_inode_item_format(
ilf->ilf_size = 2; /* format + core */
xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format));
- xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE,
- &ip->i_d,
- xfs_icdinode_size(ip->i_d.di_version));
-
+ xfs_inode_item_format_core(ip, lv, &vecp);
xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp);
if (XFS_IFORK_Q(ip)) {
xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp);