Merge branch 'xfs-gut-icdinode-4.6' into for-next

This commit is contained in:
Dave Chinner 2016-03-07 09:30:32 +11:00
commit a2bbcb60ff
23 changed files with 429 additions and 308 deletions

View File

@ -912,7 +912,7 @@ xfs_bmap_local_to_extents(
* We don't want to deal with the case of keeping inode data inline yet. * We don't want to deal with the case of keeping inode data inline yet.
* So sending the data fork of a regular inode is invalid. * So sending the data fork of a regular inode is invalid.
*/ */
ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK)); ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
ifp = XFS_IFORK_PTR(ip, whichfork); ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
@ -1079,7 +1079,7 @@ xfs_bmap_add_attrfork_local(
if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip)) if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
return 0; return 0;
if (S_ISDIR(ip->i_d.di_mode)) { if (S_ISDIR(VFS_I(ip)->i_mode)) {
memset(&dargs, 0, sizeof(dargs)); memset(&dargs, 0, sizeof(dargs));
dargs.geo = ip->i_mount->m_dir_geo; dargs.geo = ip->i_mount->m_dir_geo;
dargs.dp = ip; dargs.dp = ip;
@ -1091,7 +1091,7 @@ xfs_bmap_add_attrfork_local(
return xfs_dir2_sf_to_block(&dargs); return xfs_dir2_sf_to_block(&dargs);
} }
if (S_ISLNK(ip->i_d.di_mode)) if (S_ISLNK(VFS_I(ip)->i_mode))
return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, return xfs_bmap_local_to_extents(tp, ip, firstblock, 1,
flags, XFS_DATA_FORK, flags, XFS_DATA_FORK,
xfs_symlink_local_to_remote); xfs_symlink_local_to_remote);

View File

@ -176,7 +176,7 @@ xfs_dir_isempty(
{ {
xfs_dir2_sf_hdr_t *sfp; xfs_dir2_sf_hdr_t *sfp;
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
if (dp->i_d.di_size == 0) /* might happen during shutdown. */ if (dp->i_d.di_size == 0) /* might happen during shutdown. */
return 1; return 1;
if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
@ -231,7 +231,7 @@ xfs_dir_init(
struct xfs_da_args *args; struct xfs_da_args *args;
int error; int error;
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
if (error) if (error)
return error; return error;
@ -266,7 +266,7 @@ xfs_dir_createname(
int rval; int rval;
int v; /* type-checking value */ int v; /* type-checking value */
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
if (inum) { if (inum) {
rval = xfs_dir_ino_validate(tp->t_mountp, inum); rval = xfs_dir_ino_validate(tp->t_mountp, inum);
if (rval) if (rval)
@ -364,7 +364,7 @@ xfs_dir_lookup(
int v; /* type-checking value */ int v; /* type-checking value */
int lock_mode; int lock_mode;
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
XFS_STATS_INC(dp->i_mount, xs_dir_lookup); XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
/* /*
@ -443,7 +443,7 @@ xfs_dir_removename(
int rval; int rval;
int v; /* type-checking value */ int v; /* type-checking value */
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
XFS_STATS_INC(dp->i_mount, xs_dir_remove); XFS_STATS_INC(dp->i_mount, xs_dir_remove);
args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
@ -505,7 +505,7 @@ xfs_dir_replace(
int rval; int rval;
int v; /* type-checking value */ int v; /* type-checking value */
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
rval = xfs_dir_ino_validate(tp->t_mountp, inum); rval = xfs_dir_ino_validate(tp->t_mountp, inum);
if (rval) if (rval)

View File

@ -195,28 +195,50 @@ xfs_imap_to_bp(
} }
void void
xfs_dinode_from_disk( xfs_inode_from_disk(
xfs_icdinode_t *to, struct xfs_inode *ip,
xfs_dinode_t *from) struct xfs_dinode *from)
{ {
to->di_magic = be16_to_cpu(from->di_magic); struct xfs_icdinode *to = &ip->i_d;
to->di_mode = be16_to_cpu(from->di_mode); struct inode *inode = VFS_I(ip);
to->di_version = from ->di_version;
/*
* Convert v1 inodes immediately to v2 inode format as this is the
* minimum inode version format we support in the rest of the code.
*/
to->di_version = from->di_version;
if (to->di_version == 1) {
set_nlink(inode, be16_to_cpu(from->di_onlink));
to->di_projid_lo = 0;
to->di_projid_hi = 0;
to->di_version = 2;
} else {
set_nlink(inode, be32_to_cpu(from->di_nlink));
to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
}
to->di_format = from->di_format; to->di_format = from->di_format;
to->di_onlink = be16_to_cpu(from->di_onlink);
to->di_uid = be32_to_cpu(from->di_uid); to->di_uid = be32_to_cpu(from->di_uid);
to->di_gid = be32_to_cpu(from->di_gid); to->di_gid = be32_to_cpu(from->di_gid);
to->di_nlink = be32_to_cpu(from->di_nlink);
to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_flushiter = be16_to_cpu(from->di_flushiter); to->di_flushiter = be16_to_cpu(from->di_flushiter);
to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
to->di_atime.t_nsec = be32_to_cpu(from->di_atime.t_nsec); /*
to->di_mtime.t_sec = be32_to_cpu(from->di_mtime.t_sec); * Time is signed, so need to convert to signed 32 bit before
to->di_mtime.t_nsec = be32_to_cpu(from->di_mtime.t_nsec); * storing in inode timestamp which may be 64 bit. Otherwise
to->di_ctime.t_sec = be32_to_cpu(from->di_ctime.t_sec); * a time before epoch is converted to a time long after epoch
to->di_ctime.t_nsec = be32_to_cpu(from->di_ctime.t_nsec); * on 64 bit systems.
*/
inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec);
inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec);
inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec);
inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec);
inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec);
inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec);
inode->i_generation = be32_to_cpu(from->di_gen);
inode->i_mode = be16_to_cpu(from->di_mode);
to->di_size = be64_to_cpu(from->di_size); to->di_size = be64_to_cpu(from->di_size);
to->di_nblocks = be64_to_cpu(from->di_nblocks); to->di_nblocks = be64_to_cpu(from->di_nblocks);
to->di_extsize = be32_to_cpu(from->di_extsize); to->di_extsize = be32_to_cpu(from->di_extsize);
@ -227,42 +249,96 @@ xfs_dinode_from_disk(
to->di_dmevmask = be32_to_cpu(from->di_dmevmask); to->di_dmevmask = be32_to_cpu(from->di_dmevmask);
to->di_dmstate = be16_to_cpu(from->di_dmstate); to->di_dmstate = be16_to_cpu(from->di_dmstate);
to->di_flags = be16_to_cpu(from->di_flags); to->di_flags = be16_to_cpu(from->di_flags);
to->di_gen = be32_to_cpu(from->di_gen);
if (to->di_version == 3) { if (to->di_version == 3) {
to->di_changecount = be64_to_cpu(from->di_changecount); inode->i_version = be64_to_cpu(from->di_changecount);
to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec);
to->di_flags2 = be64_to_cpu(from->di_flags2); to->di_flags2 = be64_to_cpu(from->di_flags2);
to->di_ino = be64_to_cpu(from->di_ino);
to->di_lsn = be64_to_cpu(from->di_lsn);
memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
uuid_copy(&to->di_uuid, &from->di_uuid);
} }
} }
void void
xfs_dinode_to_disk( xfs_inode_to_disk(
xfs_dinode_t *to, struct xfs_inode *ip,
xfs_icdinode_t *from) struct xfs_dinode *to,
xfs_lsn_t lsn)
{
struct xfs_icdinode *from = &ip->i_d;
struct inode *inode = VFS_I(ip);
to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
to->di_onlink = 0;
to->di_version = from->di_version;
to->di_format = from->di_format;
to->di_uid = cpu_to_be32(from->di_uid);
to->di_gid = cpu_to_be32(from->di_gid);
to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
memset(to->di_pad, 0, sizeof(to->di_pad));
to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec);
to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec);
to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec);
to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec);
to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec);
to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec);
to->di_nlink = cpu_to_be32(inode->i_nlink);
to->di_gen = cpu_to_be32(inode->i_generation);
to->di_mode = cpu_to_be16(inode->i_mode);
to->di_size = cpu_to_be64(from->di_size);
to->di_nblocks = cpu_to_be64(from->di_nblocks);
to->di_extsize = cpu_to_be32(from->di_extsize);
to->di_nextents = cpu_to_be32(from->di_nextents);
to->di_anextents = cpu_to_be16(from->di_anextents);
to->di_forkoff = from->di_forkoff;
to->di_aformat = from->di_aformat;
to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
to->di_dmstate = cpu_to_be16(from->di_dmstate);
to->di_flags = cpu_to_be16(from->di_flags);
if (from->di_version == 3) {
to->di_changecount = cpu_to_be64(inode->i_version);
to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
to->di_flags2 = cpu_to_be64(from->di_flags2);
to->di_ino = cpu_to_be64(ip->i_ino);
to->di_lsn = cpu_to_be64(lsn);
memset(to->di_pad2, 0, sizeof(to->di_pad2));
uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid);
to->di_flushiter = 0;
} else {
to->di_flushiter = cpu_to_be16(from->di_flushiter);
}
}
void
xfs_log_dinode_to_disk(
struct xfs_log_dinode *from,
struct xfs_dinode *to)
{ {
to->di_magic = cpu_to_be16(from->di_magic); to->di_magic = cpu_to_be16(from->di_magic);
to->di_mode = cpu_to_be16(from->di_mode); to->di_mode = cpu_to_be16(from->di_mode);
to->di_version = from ->di_version; to->di_version = from->di_version;
to->di_format = from->di_format; to->di_format = from->di_format;
to->di_onlink = cpu_to_be16(from->di_onlink); to->di_onlink = 0;
to->di_uid = cpu_to_be32(from->di_uid); to->di_uid = cpu_to_be32(from->di_uid);
to->di_gid = cpu_to_be32(from->di_gid); to->di_gid = cpu_to_be32(from->di_gid);
to->di_nlink = cpu_to_be32(from->di_nlink); to->di_nlink = cpu_to_be32(from->di_nlink);
to->di_projid_lo = cpu_to_be16(from->di_projid_lo); to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
to->di_projid_hi = cpu_to_be16(from->di_projid_hi); to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec); to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec); to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec); to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec); to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec); to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
to->di_size = cpu_to_be64(from->di_size); to->di_size = cpu_to_be64(from->di_size);
to->di_nblocks = cpu_to_be64(from->di_nblocks); to->di_nblocks = cpu_to_be64(from->di_nblocks);
to->di_extsize = cpu_to_be32(from->di_extsize); to->di_extsize = cpu_to_be32(from->di_extsize);
@ -367,13 +443,10 @@ xfs_iread(
!(mp->m_flags & XFS_MOUNT_IKEEP)) { !(mp->m_flags & XFS_MOUNT_IKEEP)) {
/* initialise the on-disk inode core */ /* initialise the on-disk inode core */
memset(&ip->i_d, 0, sizeof(ip->i_d)); memset(&ip->i_d, 0, sizeof(ip->i_d));
ip->i_d.di_magic = XFS_DINODE_MAGIC; VFS_I(ip)->i_generation = prandom_u32();
ip->i_d.di_gen = prandom_u32(); if (xfs_sb_version_hascrc(&mp->m_sb))
if (xfs_sb_version_hascrc(&mp->m_sb)) {
ip->i_d.di_version = 3; ip->i_d.di_version = 3;
ip->i_d.di_ino = ip->i_ino; else
uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid);
} else
ip->i_d.di_version = 2; ip->i_d.di_version = 2;
return 0; return 0;
} }
@ -403,7 +476,7 @@ xfs_iread(
* Otherwise, just get the truly permanent information. * Otherwise, just get the truly permanent information.
*/ */
if (dip->di_mode) { if (dip->di_mode) {
xfs_dinode_from_disk(&ip->i_d, dip); xfs_inode_from_disk(ip, dip);
error = xfs_iformat_fork(ip, dip); error = xfs_iformat_fork(ip, dip);
if (error) { if (error) {
#ifdef DEBUG #ifdef DEBUG
@ -417,16 +490,10 @@ xfs_iread(
* Partial initialisation of the in-core inode. Just the bits * Partial initialisation of the in-core inode. Just the bits
* that xfs_ialloc won't overwrite or relies on being correct. * that xfs_ialloc won't overwrite or relies on being correct.
*/ */
ip->i_d.di_magic = be16_to_cpu(dip->di_magic);
ip->i_d.di_version = dip->di_version; ip->i_d.di_version = dip->di_version;
ip->i_d.di_gen = be32_to_cpu(dip->di_gen); VFS_I(ip)->i_generation = be32_to_cpu(dip->di_gen);
ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter); ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter);
if (dip->di_version == 3) {
ip->i_d.di_ino = be64_to_cpu(dip->di_ino);
uuid_copy(&ip->i_d.di_uuid, &dip->di_uuid);
}
/* /*
* Make sure to pull in the mode here as well in * Make sure to pull in the mode here as well in
* case the inode is released without being used. * case the inode is released without being used.
@ -434,25 +501,10 @@ xfs_iread(
* the inode is already free and not try to mess * the inode is already free and not try to mess
* with the uninitialized part of it. * with the uninitialized part of it.
*/ */
ip->i_d.di_mode = 0; VFS_I(ip)->i_mode = 0;
}
/*
* Automatically convert version 1 inode formats in memory to version 2
* inode format. If the inode is modified, it will get logged and
* rewritten as a version 2 inode. We can do this because we set the
* superblock feature bit for v2 inodes unconditionally during mount
* and it means the reast of the code can assume the inode version is 2
* or higher.
*/
if (ip->i_d.di_version == 1) {
ip->i_d.di_version = 2;
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
ip->i_d.di_nlink = ip->i_d.di_onlink;
ip->i_d.di_onlink = 0;
xfs_set_projid(ip, 0);
} }
ASSERT(ip->i_d.di_version >= 2);
ip->i_delayed_blks = 0; ip->i_delayed_blks = 0;
/* /*

View File

@ -20,7 +20,36 @@
struct xfs_inode; struct xfs_inode;
struct xfs_dinode; struct xfs_dinode;
struct xfs_icdinode;
/*
* In memory representation of the XFS inode. This is held in the in-core struct
* xfs_inode and represents the current on disk values but the structure is not
* in on-disk format. That is, this structure is always translated to on-disk
* format specific structures at the appropriate time.
*/
struct xfs_icdinode {
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_flushiter; /* incremented on flush */
__uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */
__uint16_t di_projid_lo; /* lower part of owner's project id */
__uint16_t di_projid_hi; /* higher part of owner's project id */
xfs_fsize_t di_size; /* number of bytes in file */
xfs_rfsblock_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
xfs_extnum_t di_nextents; /* number of extents in data fork */
xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
__uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
__int8_t di_aformat; /* format of attr fork's data */
__uint32_t di_dmevmask; /* DMIG event mask */
__uint16_t di_dmstate; /* DMIG state info */
__uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
__uint64_t di_flags2; /* more random flags */
xfs_ictimestamp_t di_crtime; /* time created */
};
/* /*
* Inode location information. Stored in the inode and passed to * Inode location information. Stored in the inode and passed to
@ -38,8 +67,11 @@ int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *,
int xfs_iread(struct xfs_mount *, struct xfs_trans *, int xfs_iread(struct xfs_mount *, struct xfs_trans *,
struct xfs_inode *, uint); struct xfs_inode *, uint);
void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
void xfs_dinode_to_disk(struct xfs_dinode *to, struct xfs_icdinode *from); void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to,
void xfs_dinode_from_disk(struct xfs_icdinode *to, struct xfs_dinode *from); xfs_lsn_t lsn);
void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
void xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
struct xfs_dinode *to);
#if defined(DEBUG) #if defined(DEBUG)
void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);

View File

@ -121,7 +121,7 @@ xfs_iformat_fork(
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
switch (ip->i_d.di_mode & S_IFMT) { switch (VFS_I(ip)->i_mode & S_IFMT) {
case S_IFIFO: case S_IFIFO:
case S_IFCHR: case S_IFCHR:
case S_IFBLK: case S_IFBLK:

View File

@ -290,6 +290,7 @@ typedef struct xfs_inode_log_format_64 {
__int32_t ilf_boffset; /* off of inode in buffer */ __int32_t ilf_boffset; /* off of inode in buffer */
} xfs_inode_log_format_64_t; } xfs_inode_log_format_64_t;
/* /*
* Flags for xfs_trans_log_inode flags field. * Flags for xfs_trans_log_inode flags field.
*/ */
@ -360,15 +361,15 @@ typedef struct xfs_ictimestamp {
} xfs_ictimestamp_t; } xfs_ictimestamp_t;
/* /*
* NOTE: This structure must be kept identical to struct xfs_dinode * Define the format of the inode core that is logged. This structure must be
* except for the endianness annotations. * kept identical to struct xfs_dinode except for the endianness annotations.
*/ */
typedef struct xfs_icdinode { struct xfs_log_dinode {
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__uint16_t di_mode; /* mode and type of file */ __uint16_t di_mode; /* mode and type of file */
__int8_t di_version; /* inode version */ __int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */ __int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */ __uint8_t di_pad3[2]; /* unused in v2/3 inodes */
__uint32_t di_uid; /* owner's user id */ __uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */ __uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */ __uint32_t di_nlink; /* number of links to file */
@ -407,13 +408,13 @@ typedef struct xfs_icdinode {
uuid_t di_uuid; /* UUID of the filesystem */ uuid_t di_uuid; /* UUID of the filesystem */
/* structure must be padded to 64 bit alignment */ /* structure must be padded to 64 bit alignment */
} xfs_icdinode_t; };
static inline uint xfs_icdinode_size(int version) static inline uint xfs_log_dinode_size(int version)
{ {
if (version == 3) if (version == 3)
return sizeof(struct xfs_icdinode); return sizeof(struct xfs_log_dinode);
return offsetof(struct xfs_icdinode, di_next_unlinked); return offsetof(struct xfs_log_dinode, di_next_unlinked);
} }
/* /*

View File

@ -1011,7 +1011,7 @@ xfs_rtfree_extent(
mp->m_sb.sb_rextents) { mp->m_sb.sb_rextents) {
if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; *(__uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
} }
return 0; return 0;

View File

@ -823,7 +823,7 @@ bool
xfs_can_free_eofblocks(struct xfs_inode *ip, bool force) xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
{ {
/* prealloc/delalloc exists only on regular files */ /* prealloc/delalloc exists only on regular files */
if (!S_ISREG(ip->i_d.di_mode)) if (!S_ISREG(VFS_I(ip)->i_mode))
return false; return false;
/* /*
@ -1728,7 +1728,7 @@ xfs_swap_extents(
xfs_lock_two_inodes(ip, tip, XFS_MMAPLOCK_EXCL); xfs_lock_two_inodes(ip, tip, XFS_MMAPLOCK_EXCL);
/* Verify that both files have the same format */ /* Verify that both files have the same format */
if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { if ((VFS_I(ip)->i_mode & S_IFMT) != (VFS_I(tip)->i_mode & S_IFMT)) {
error = -EINVAL; error = -EINVAL;
goto out_unlock; goto out_unlock;
} }

View File

@ -665,7 +665,7 @@ xfs_readdir(
if (XFS_FORCED_SHUTDOWN(dp->i_mount)) if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return -EIO; return -EIO;
ASSERT(S_ISDIR(dp->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
XFS_STATS_INC(dp->i_mount, xs_dir_getdents); XFS_STATS_INC(dp->i_mount, xs_dir_getdents);
args.dp = dp; args.dp = dp;

View File

@ -152,7 +152,7 @@ xfs_nfs_get_inode(
return ERR_PTR(error); return ERR_PTR(error);
} }
if (ip->i_d.di_gen != generation) { if (VFS_I(ip)->i_generation != generation) {
IRELE(ip); IRELE(ip);
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
} }

View File

@ -156,9 +156,9 @@ xfs_update_prealloc_flags(
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
if (!(flags & XFS_PREALLOC_INVISIBLE)) { if (!(flags & XFS_PREALLOC_INVISIBLE)) {
ip->i_d.di_mode &= ~S_ISUID; VFS_I(ip)->i_mode &= ~S_ISUID;
if (ip->i_d.di_mode & S_IXGRP) if (VFS_I(ip)->i_mode & S_IXGRP)
ip->i_d.di_mode &= ~S_ISGID; VFS_I(ip)->i_mode &= ~S_ISGID;
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
} }

View File

@ -151,7 +151,7 @@ xfs_filestream_pick_ag(
xfs_agnumber_t ag, max_ag = NULLAGNUMBER; xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
int err, trylock, nscan; int err, trylock, nscan;
ASSERT(S_ISDIR(ip->i_d.di_mode)); ASSERT(S_ISDIR(VFS_I(ip)->i_mode));
/* 2% of an AG's blocks must be free for it to be chosen. */ /* 2% of an AG's blocks must be free for it to be chosen. */
minfree = mp->m_sb.sb_agblocks / 50; minfree = mp->m_sb.sb_agblocks / 50;
@ -319,7 +319,7 @@ xfs_filestream_lookup_ag(
xfs_agnumber_t startag, ag = NULLAGNUMBER; xfs_agnumber_t startag, ag = NULLAGNUMBER;
struct xfs_mru_cache_elem *mru; struct xfs_mru_cache_elem *mru;
ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT(S_ISREG(VFS_I(ip)->i_mode));
pip = xfs_filestream_get_parent(ip); pip = xfs_filestream_get_parent(ip);
if (!pip) if (!pip)

View File

@ -63,6 +63,9 @@ xfs_inode_alloc(
return NULL; return NULL;
} }
/* VFS doesn't initialise i_mode! */
VFS_I(ip)->i_mode = 0;
XFS_STATS_INC(mp, vn_active); XFS_STATS_INC(mp, vn_active);
ASSERT(atomic_read(&ip->i_pincount) == 0); ASSERT(atomic_read(&ip->i_pincount) == 0);
ASSERT(!spin_is_locked(&ip->i_flags_lock)); ASSERT(!spin_is_locked(&ip->i_flags_lock));
@ -79,7 +82,7 @@ xfs_inode_alloc(
memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
ip->i_flags = 0; ip->i_flags = 0;
ip->i_delayed_blks = 0; ip->i_delayed_blks = 0;
memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); memset(&ip->i_d, 0, sizeof(ip->i_d));
return ip; return ip;
} }
@ -98,7 +101,7 @@ void
xfs_inode_free( xfs_inode_free(
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
switch (ip->i_d.di_mode & S_IFMT) { switch (VFS_I(ip)->i_mode & S_IFMT) {
case S_IFREG: case S_IFREG:
case S_IFDIR: case S_IFDIR:
case S_IFLNK: case S_IFLNK:
@ -134,6 +137,34 @@ xfs_inode_free(
call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
} }
/*
* When we recycle a reclaimable inode, we need to re-initialise the VFS inode
* part of the structure. This is made more complex by the fact we store
* information about the on-disk values in the VFS inode and so we can't just
* overwrite the values unconditionally. Hence we save the parameters we
* need to retain across reinitialisation, and rewrite them into the VFS inode
* after reinitialisation even if it fails.
*/
static int
xfs_reinit_inode(
struct xfs_mount *mp,
struct inode *inode)
{
int error;
uint32_t nlink = inode->i_nlink;
uint32_t generation = inode->i_generation;
uint64_t version = inode->i_version;
umode_t mode = inode->i_mode;
error = inode_init_always(mp->m_super, inode);
set_nlink(inode, nlink);
inode->i_generation = generation;
inode->i_version = version;
inode->i_mode = mode;
return error;
}
/* /*
* Check the validity of the inode we just found it the cache * Check the validity of the inode we just found it the cache
*/ */
@ -185,7 +216,7 @@ xfs_iget_cache_hit(
/* /*
* If lookup is racing with unlink return an error immediately. * If lookup is racing with unlink return an error immediately.
*/ */
if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { if (VFS_I(ip)->i_mode == 0 && !(flags & XFS_IGET_CREATE)) {
error = -ENOENT; error = -ENOENT;
goto out_error; goto out_error;
} }
@ -208,7 +239,7 @@ xfs_iget_cache_hit(
spin_unlock(&ip->i_flags_lock); spin_unlock(&ip->i_flags_lock);
rcu_read_unlock(); rcu_read_unlock();
error = inode_init_always(mp->m_super, inode); error = xfs_reinit_inode(mp, inode);
if (error) { if (error) {
/* /*
* Re-initializing the inode failed, and we are in deep * Re-initializing the inode failed, and we are in deep
@ -295,7 +326,7 @@ xfs_iget_cache_miss(
trace_xfs_iget_miss(ip); trace_xfs_iget_miss(ip);
if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { if ((VFS_I(ip)->i_mode == 0) && !(flags & XFS_IGET_CREATE)) {
error = -ENOENT; error = -ENOENT;
goto out_destroy; goto out_destroy;
} }
@ -444,7 +475,7 @@ again:
* If we have a real type for an on-disk inode, we can setup the inode * If we have a real type for an on-disk inode, we can setup the inode
* now. If it's a new inode being created, xfs_ialloc will handle it. * now. If it's a new inode being created, xfs_ialloc will handle it.
*/ */
if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0) if (xfs_iflags_test(ip, XFS_INEW) && VFS_I(ip)->i_mode != 0)
xfs_setup_existing_inode(ip); xfs_setup_existing_inode(ip);
return 0; return 0;

View File

@ -57,9 +57,9 @@ kmem_zone_t *xfs_inode_zone;
*/ */
#define XFS_ITRUNC_MAX_EXTENTS 2 #define XFS_ITRUNC_MAX_EXTENTS 2
STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); STATIC int xfs_iflush_int(struct xfs_inode *, struct xfs_buf *);
STATIC int xfs_iunlink(struct xfs_trans *, struct xfs_inode *);
STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *); STATIC int xfs_iunlink_remove(struct xfs_trans *, struct xfs_inode *);
/* /*
* helper function to extract extent size hint from inode * helper function to extract extent size hint from inode
@ -766,6 +766,7 @@ xfs_ialloc(
uint flags; uint flags;
int error; int error;
struct timespec tv; struct timespec tv;
struct inode *inode;
/* /*
* Call the space management code to pick * Call the space management code to pick
@ -791,6 +792,7 @@ xfs_ialloc(
if (error) if (error)
return error; return error;
ASSERT(ip != NULL); ASSERT(ip != NULL);
inode = VFS_I(ip);
/* /*
* We always convert v1 inodes to v2 now - we only support filesystems * We always convert v1 inodes to v2 now - we only support filesystems
@ -800,20 +802,16 @@ xfs_ialloc(
if (ip->i_d.di_version == 1) if (ip->i_d.di_version == 1)
ip->i_d.di_version = 2; ip->i_d.di_version = 2;
ip->i_d.di_mode = mode; inode->i_mode = mode;
ip->i_d.di_onlink = 0; set_nlink(inode, nlink);
ip->i_d.di_nlink = nlink;
ASSERT(ip->i_d.di_nlink == nlink);
ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid()); ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid());
ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid()); ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid());
xfs_set_projid(ip, prid); xfs_set_projid(ip, prid);
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
if (pip && XFS_INHERIT_GID(pip)) { if (pip && XFS_INHERIT_GID(pip)) {
ip->i_d.di_gid = pip->i_d.di_gid; ip->i_d.di_gid = pip->i_d.di_gid;
if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) { if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode))
ip->i_d.di_mode |= S_ISGID; inode->i_mode |= S_ISGID;
}
} }
/* /*
@ -822,38 +820,29 @@ xfs_ialloc(
* (and only if the irix_sgid_inherit compatibility variable is set). * (and only if the irix_sgid_inherit compatibility variable is set).
*/ */
if ((irix_sgid_inherit) && if ((irix_sgid_inherit) &&
(ip->i_d.di_mode & S_ISGID) && (inode->i_mode & S_ISGID) &&
(!in_group_p(xfs_gid_to_kgid(ip->i_d.di_gid)))) { (!in_group_p(xfs_gid_to_kgid(ip->i_d.di_gid))))
ip->i_d.di_mode &= ~S_ISGID; inode->i_mode &= ~S_ISGID;
}
ip->i_d.di_size = 0; ip->i_d.di_size = 0;
ip->i_d.di_nextents = 0; ip->i_d.di_nextents = 0;
ASSERT(ip->i_d.di_nblocks == 0); ASSERT(ip->i_d.di_nblocks == 0);
tv = current_fs_time(mp->m_super); tv = current_fs_time(mp->m_super);
ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; inode->i_mtime = tv;
ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; inode->i_atime = tv;
ip->i_d.di_atime = ip->i_d.di_mtime; inode->i_ctime = tv;
ip->i_d.di_ctime = ip->i_d.di_mtime;
/*
* di_gen will have been taken care of in xfs_iread.
*/
ip->i_d.di_extsize = 0; ip->i_d.di_extsize = 0;
ip->i_d.di_dmevmask = 0; ip->i_d.di_dmevmask = 0;
ip->i_d.di_dmstate = 0; ip->i_d.di_dmstate = 0;
ip->i_d.di_flags = 0; ip->i_d.di_flags = 0;
if (ip->i_d.di_version == 3) { if (ip->i_d.di_version == 3) {
ASSERT(ip->i_d.di_ino == ino); inode->i_version = 1;
ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
ip->i_d.di_crc = 0;
ip->i_d.di_changecount = 1;
ip->i_d.di_lsn = 0;
ip->i_d.di_flags2 = 0; ip->i_d.di_flags2 = 0;
memset(&(ip->i_d.di_pad2[0]), 0, sizeof(ip->i_d.di_pad2)); ip->i_d.di_crtime.t_sec = (__int32_t)tv.tv_sec;
ip->i_d.di_crtime = ip->i_d.di_mtime; ip->i_d.di_crtime.t_nsec = (__int32_t)tv.tv_nsec;
} }
@ -1092,35 +1081,24 @@ xfs_dir_ialloc(
} }
/* /*
* Decrement the link count on an inode & log the change. * Decrement the link count on an inode & log the change. If this causes the
* If this causes the link count to go to zero, initiate the * link count to go to zero, move the inode to AGI unlinked list so that it can
* logging activity required to truncate a file. * be freed when the last active reference goes away via xfs_inactive().
*/ */
int /* error */ int /* error */
xfs_droplink( xfs_droplink(
xfs_trans_t *tp, xfs_trans_t *tp,
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
int error;
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
ASSERT (ip->i_d.di_nlink > 0);
ip->i_d.di_nlink--;
drop_nlink(VFS_I(ip)); drop_nlink(VFS_I(ip));
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = 0; if (VFS_I(ip)->i_nlink)
if (ip->i_d.di_nlink == 0) { return 0;
/*
* We're dropping the last link to this file. return xfs_iunlink(tp, ip);
* Move the on-disk inode to the AGI unlinked list.
* From xfs_inactive() we will pull the inode from
* the list and free it.
*/
error = xfs_iunlink(tp, ip);
}
return error;
} }
/* /*
@ -1134,8 +1112,6 @@ xfs_bumplink(
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
ASSERT(ip->i_d.di_version > 1); ASSERT(ip->i_d.di_version > 1);
ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE));
ip->i_d.di_nlink++;
inc_nlink(VFS_I(ip)); inc_nlink(VFS_I(ip));
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
return 0; return 0;
@ -1393,7 +1369,6 @@ xfs_create_tmpfile(
*/ */
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
ip->i_d.di_nlink--;
error = xfs_iunlink(tp, ip); error = xfs_iunlink(tp, ip);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
@ -1444,7 +1419,7 @@ xfs_link(
trace_xfs_link(tdp, target_name); trace_xfs_link(tdp, target_name);
ASSERT(!S_ISDIR(sip->i_d.di_mode)); ASSERT(!S_ISDIR(VFS_I(sip)->i_mode));
if (XFS_FORCED_SHUTDOWN(mp)) if (XFS_FORCED_SHUTDOWN(mp))
return -EIO; return -EIO;
@ -1492,7 +1467,10 @@ xfs_link(
xfs_bmap_init(&free_list, &first_block); xfs_bmap_init(&free_list, &first_block);
if (sip->i_d.di_nlink == 0) { /*
* Handle initial link state of O_TMPFILE inode
*/
if (VFS_I(sip)->i_nlink == 0) {
error = xfs_iunlink_remove(tp, sip); error = xfs_iunlink_remove(tp, sip);
if (error) if (error)
goto error_return; goto error_return;
@ -1648,7 +1626,7 @@ xfs_release(
xfs_mount_t *mp = ip->i_mount; xfs_mount_t *mp = ip->i_mount;
int error; int error;
if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0)) if (!S_ISREG(VFS_I(ip)->i_mode) || (VFS_I(ip)->i_mode == 0))
return 0; return 0;
/* If this is a read-only mount, don't do this (would generate I/O) */ /* If this is a read-only mount, don't do this (would generate I/O) */
@ -1679,7 +1657,7 @@ xfs_release(
} }
} }
if (ip->i_d.di_nlink == 0) if (VFS_I(ip)->i_nlink == 0)
return 0; return 0;
if (xfs_can_free_eofblocks(ip, false)) { if (xfs_can_free_eofblocks(ip, false)) {
@ -1883,7 +1861,7 @@ xfs_inactive(
* If the inode is already free, then there can be nothing * If the inode is already free, then there can be nothing
* to clean up here. * to clean up here.
*/ */
if (ip->i_d.di_mode == 0) { if (VFS_I(ip)->i_mode == 0) {
ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_real_bytes == 0);
ASSERT(ip->i_df.if_broot_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0);
return; return;
@ -1895,7 +1873,7 @@ xfs_inactive(
if (mp->m_flags & XFS_MOUNT_RDONLY) if (mp->m_flags & XFS_MOUNT_RDONLY)
return; return;
if (ip->i_d.di_nlink != 0) { if (VFS_I(ip)->i_nlink != 0) {
/* /*
* force is true because we are evicting an inode from the * force is true because we are evicting an inode from the
* cache. Post-eof blocks must be freed, lest we end up with * cache. Post-eof blocks must be freed, lest we end up with
@ -1907,7 +1885,7 @@ xfs_inactive(
return; return;
} }
if (S_ISREG(ip->i_d.di_mode) && if (S_ISREG(VFS_I(ip)->i_mode) &&
(ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 || (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0)) ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
truncate = 1; truncate = 1;
@ -1916,7 +1894,7 @@ xfs_inactive(
if (error) if (error)
return; return;
if (S_ISLNK(ip->i_d.di_mode)) if (S_ISLNK(VFS_I(ip)->i_mode))
error = xfs_inactive_symlink(ip); error = xfs_inactive_symlink(ip);
else if (truncate) else if (truncate)
error = xfs_inactive_truncate(ip); error = xfs_inactive_truncate(ip);
@ -1952,16 +1930,21 @@ xfs_inactive(
} }
/* /*
* This is called when the inode's link count goes to 0. * This is called when the inode's link count goes to 0 or we are creating a
* We place the on-disk inode on a list in the AGI. It * tmpfile via O_TMPFILE. In the case of a tmpfile, @ignore_linkcount will be
* will be pulled from this list when the inode is freed. * set to true as the link count is dropped to zero by the VFS after we've
* created the file successfully, so we have to add it to the unlinked list
* while the link count is non-zero.
*
* We place the on-disk inode on a list in the AGI. It will be pulled from this
* list when the inode is freed.
*/ */
int STATIC int
xfs_iunlink( xfs_iunlink(
xfs_trans_t *tp, struct xfs_trans *tp,
xfs_inode_t *ip) struct xfs_inode *ip)
{ {
xfs_mount_t *mp; xfs_mount_t *mp = tp->t_mountp;
xfs_agi_t *agi; xfs_agi_t *agi;
xfs_dinode_t *dip; xfs_dinode_t *dip;
xfs_buf_t *agibp; xfs_buf_t *agibp;
@ -1971,10 +1954,7 @@ xfs_iunlink(
int offset; int offset;
int error; int error;
ASSERT(ip->i_d.di_nlink == 0); ASSERT(VFS_I(ip)->i_mode != 0);
ASSERT(ip->i_d.di_mode != 0);
mp = tp->t_mountp;
/* /*
* Get the agi buffer first. It ensures lock ordering * Get the agi buffer first. It ensures lock ordering
@ -2412,10 +2392,10 @@ xfs_ifree(
struct xfs_icluster xic = { 0 }; struct xfs_icluster xic = { 0 };
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT(ip->i_d.di_nlink == 0); ASSERT(VFS_I(ip)->i_nlink == 0);
ASSERT(ip->i_d.di_nextents == 0); ASSERT(ip->i_d.di_nextents == 0);
ASSERT(ip->i_d.di_anextents == 0); ASSERT(ip->i_d.di_anextents == 0);
ASSERT(ip->i_d.di_size == 0 || !S_ISREG(ip->i_d.di_mode)); ASSERT(ip->i_d.di_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
ASSERT(ip->i_d.di_nblocks == 0); ASSERT(ip->i_d.di_nblocks == 0);
/* /*
@ -2429,7 +2409,7 @@ xfs_ifree(
if (error) if (error)
return error; return error;
ip->i_d.di_mode = 0; /* mark incore inode as free */ VFS_I(ip)->i_mode = 0; /* mark incore inode as free */
ip->i_d.di_flags = 0; ip->i_d.di_flags = 0;
ip->i_d.di_dmevmask = 0; ip->i_d.di_dmevmask = 0;
ip->i_d.di_forkoff = 0; /* mark the attr fork not in use */ ip->i_d.di_forkoff = 0; /* mark the attr fork not in use */
@ -2439,7 +2419,7 @@ xfs_ifree(
* Bump the generation count so no one will be confused * Bump the generation count so no one will be confused
* by reincarnations of this inode. * by reincarnations of this inode.
*/ */
ip->i_d.di_gen++; VFS_I(ip)->i_generation++;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
if (xic.deleted) if (xic.deleted)
@ -2526,7 +2506,7 @@ xfs_remove(
{ {
xfs_mount_t *mp = dp->i_mount; xfs_mount_t *mp = dp->i_mount;
xfs_trans_t *tp = NULL; xfs_trans_t *tp = NULL;
int is_dir = S_ISDIR(ip->i_d.di_mode); int is_dir = S_ISDIR(VFS_I(ip)->i_mode);
int error = 0; int error = 0;
xfs_bmap_free_t free_list; xfs_bmap_free_t free_list;
xfs_fsblock_t first_block; xfs_fsblock_t first_block;
@ -2580,8 +2560,8 @@ xfs_remove(
* If we're removing a directory perform some additional validation. * If we're removing a directory perform some additional validation.
*/ */
if (is_dir) { if (is_dir) {
ASSERT(ip->i_d.di_nlink >= 2); ASSERT(VFS_I(ip)->i_nlink >= 2);
if (ip->i_d.di_nlink != 2) { if (VFS_I(ip)->i_nlink != 2) {
error = -ENOTEMPTY; error = -ENOTEMPTY;
goto out_trans_cancel; goto out_trans_cancel;
} }
@ -2771,7 +2751,7 @@ xfs_cross_rename(
if (dp1 != dp2) { if (dp1 != dp2) {
dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
if (S_ISDIR(ip2->i_d.di_mode)) { if (S_ISDIR(VFS_I(ip2)->i_mode)) {
error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot, error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot,
dp1->i_ino, first_block, dp1->i_ino, first_block,
free_list, spaceres); free_list, spaceres);
@ -2779,7 +2759,7 @@ xfs_cross_rename(
goto out_trans_abort; goto out_trans_abort;
/* transfer ip2 ".." reference to dp1 */ /* transfer ip2 ".." reference to dp1 */
if (!S_ISDIR(ip1->i_d.di_mode)) { if (!S_ISDIR(VFS_I(ip1)->i_mode)) {
error = xfs_droplink(tp, dp2); error = xfs_droplink(tp, dp2);
if (error) if (error)
goto out_trans_abort; goto out_trans_abort;
@ -2798,7 +2778,7 @@ xfs_cross_rename(
ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
} }
if (S_ISDIR(ip1->i_d.di_mode)) { if (S_ISDIR(VFS_I(ip1)->i_mode)) {
error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot, error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot,
dp2->i_ino, first_block, dp2->i_ino, first_block,
free_list, spaceres); free_list, spaceres);
@ -2806,7 +2786,7 @@ xfs_cross_rename(
goto out_trans_abort; goto out_trans_abort;
/* transfer ip1 ".." reference to dp2 */ /* transfer ip1 ".." reference to dp2 */
if (!S_ISDIR(ip2->i_d.di_mode)) { if (!S_ISDIR(VFS_I(ip2)->i_mode)) {
error = xfs_droplink(tp, dp1); error = xfs_droplink(tp, dp1);
if (error) if (error)
goto out_trans_abort; goto out_trans_abort;
@ -2903,7 +2883,7 @@ xfs_rename(
struct xfs_inode *inodes[__XFS_SORT_INODES]; struct xfs_inode *inodes[__XFS_SORT_INODES];
int num_inodes = __XFS_SORT_INODES; int num_inodes = __XFS_SORT_INODES;
bool new_parent = (src_dp != target_dp); bool new_parent = (src_dp != target_dp);
bool src_is_directory = S_ISDIR(src_ip->i_d.di_mode); bool src_is_directory = S_ISDIR(VFS_I(src_ip)->i_mode);
int spaceres; int spaceres;
int error; int error;
@ -3032,12 +3012,12 @@ xfs_rename(
* target and source are directories and that target can be * target and source are directories and that target can be
* destroyed, or that neither is a directory. * destroyed, or that neither is a directory.
*/ */
if (S_ISDIR(target_ip->i_d.di_mode)) { if (S_ISDIR(VFS_I(target_ip)->i_mode)) {
/* /*
* Make sure target dir is empty. * Make sure target dir is empty.
*/ */
if (!(xfs_dir_isempty(target_ip)) || if (!(xfs_dir_isempty(target_ip)) ||
(target_ip->i_d.di_nlink > 2)) { (VFS_I(target_ip)->i_nlink > 2)) {
error = -EEXIST; error = -EEXIST;
goto out_trans_cancel; goto out_trans_cancel;
} }
@ -3144,7 +3124,7 @@ xfs_rename(
* intermediate state on disk. * intermediate state on disk.
*/ */
if (wip) { if (wip) {
ASSERT(VFS_I(wip)->i_nlink == 0 && wip->i_d.di_nlink == 0); ASSERT(VFS_I(wip)->i_nlink == 0);
error = xfs_bumplink(tp, wip); error = xfs_bumplink(tp, wip);
if (error) if (error)
goto out_bmap_cancel; goto out_bmap_cancel;
@ -3462,14 +3442,7 @@ xfs_iflush_int(
__func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip); __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);
goto corrupt_out; goto corrupt_out;
} }
if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC, if (S_ISREG(VFS_I(ip)->i_mode)) {
mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) {
xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
"%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
__func__, ip->i_ino, ip, ip->i_d.di_magic);
goto corrupt_out;
}
if (S_ISREG(ip->i_d.di_mode)) {
if (XFS_TEST_ERROR( if (XFS_TEST_ERROR(
(ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
(ip->i_d.di_format != XFS_DINODE_FMT_BTREE), (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
@ -3479,7 +3452,7 @@ xfs_iflush_int(
__func__, ip->i_ino, ip); __func__, ip->i_ino, ip);
goto corrupt_out; goto corrupt_out;
} }
} else if (S_ISDIR(ip->i_d.di_mode)) { } else if (S_ISDIR(VFS_I(ip)->i_mode)) {
if (XFS_TEST_ERROR( if (XFS_TEST_ERROR(
(ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
(ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
@ -3523,12 +3496,11 @@ xfs_iflush_int(
ip->i_d.di_flushiter++; ip->i_d.di_flushiter++;
/* /*
* Copy the dirty parts of the inode into the on-disk * Copy the dirty parts of the inode into the on-disk inode. We always
* inode. We always copy out the core of the inode, * copy out the core of the inode, because if the inode is dirty at all
* because if the inode is dirty at all the core must * the core must be.
* be.
*/ */
xfs_dinode_to_disk(dip, &ip->i_d); xfs_inode_to_disk(ip, dip, iip->ili_item.li_lsn);
/* Wrap, we never let the log put out DI_MAX_FLUSH */ /* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH) if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
@ -3580,10 +3552,6 @@ xfs_iflush_int(
*/ */
xfs_buf_attach_iodone(bp, xfs_iflush_done, &iip->ili_item); xfs_buf_attach_iodone(bp, xfs_iflush_done, &iip->ili_item);
/* update the lsn in the on disk inode if required */
if (ip->i_d.di_version == 3)
dip->di_lsn = cpu_to_be64(iip->ili_item.li_lsn);
/* generate the checksum. */ /* generate the checksum. */
xfs_dinode_calc_crc(mp, dip); xfs_dinode_calc_crc(mp, dip);

View File

@ -63,7 +63,7 @@ typedef struct xfs_inode {
unsigned long i_flags; /* see defined flags below */ unsigned long i_flags; /* see defined flags below */
unsigned int i_delayed_blks; /* count of delay alloc blks */ unsigned int i_delayed_blks; /* count of delay alloc blks */
xfs_icdinode_t i_d; /* most of ondisk inode */ struct xfs_icdinode i_d; /* most of ondisk inode */
/* VFS inode */ /* VFS inode */
struct inode i_vnode; /* embedded VFS inode */ struct inode i_vnode; /* embedded VFS inode */
@ -88,7 +88,7 @@ static inline struct inode *VFS_I(struct xfs_inode *ip)
*/ */
static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip) static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip)
{ {
if (S_ISREG(ip->i_d.di_mode)) if (S_ISREG(VFS_I(ip)->i_mode))
return i_size_read(VFS_I(ip)); return i_size_read(VFS_I(ip));
return ip->i_d.di_size; return ip->i_d.di_size;
} }
@ -369,7 +369,7 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
*/ */
#define XFS_INHERIT_GID(pip) \ #define XFS_INHERIT_GID(pip) \
(((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \ (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
((pip)->i_d.di_mode & S_ISGID)) (VFS_I(pip)->i_mode & S_ISGID))
int xfs_release(struct xfs_inode *ip); int xfs_release(struct xfs_inode *ip);
void xfs_inactive(struct xfs_inode *ip); void xfs_inactive(struct xfs_inode *ip);
@ -405,8 +405,6 @@ int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
struct xfs_bmap_free *); struct xfs_bmap_free *);
int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *, int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *,
int, xfs_fsize_t); int, xfs_fsize_t);
int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
void xfs_iext_realloc(xfs_inode_t *, int, int); void xfs_iext_realloc(xfs_inode_t *, int, int);
void xfs_iunpin_wait(xfs_inode_t *); void xfs_iunpin_wait(xfs_inode_t *);

View File

@ -135,7 +135,7 @@ xfs_inode_item_size(
*nvecs += 2; *nvecs += 2;
*nbytes += sizeof(struct xfs_inode_log_format) + *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); xfs_inode_item_data_fork_size(iip, nvecs, nbytes);
if (XFS_IFORK_Q(ip)) if (XFS_IFORK_Q(ip))
@ -322,6 +322,81 @@ xfs_inode_item_format_attr_fork(
} }
} }
static void
xfs_inode_to_log_dinode(
struct xfs_inode *ip,
struct xfs_log_dinode *to,
xfs_lsn_t lsn)
{
struct xfs_icdinode *from = &ip->i_d;
struct inode *inode = VFS_I(ip);
to->di_magic = XFS_DINODE_MAGIC;
to->di_version = from->di_version;
to->di_format = from->di_format;
to->di_uid = from->di_uid;
to->di_gid = from->di_gid;
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));
memset(to->di_pad3, 0, sizeof(to->di_pad3));
to->di_atime.t_sec = inode->i_atime.tv_sec;
to->di_atime.t_nsec = inode->i_atime.tv_nsec;
to->di_mtime.t_sec = inode->i_mtime.tv_sec;
to->di_mtime.t_nsec = inode->i_mtime.tv_nsec;
to->di_ctime.t_sec = inode->i_ctime.tv_sec;
to->di_ctime.t_nsec = inode->i_ctime.tv_nsec;
to->di_nlink = inode->i_nlink;
to->di_gen = inode->i_generation;
to->di_mode = inode->i_mode;
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;
if (from->di_version == 3) {
to->di_changecount = inode->i_version;
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 = ip->i_ino;
to->di_lsn = lsn;
memset(to->di_pad2, 0, sizeof(to->di_pad2));
uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_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_inode_to_log_dinode(ip, dic, ip->i_itemp->ili_item.li_lsn);
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 * 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, * log item. It fills the first item with an inode log format structure,
@ -351,10 +426,7 @@ xfs_inode_item_format(
ilf->ilf_size = 2; /* format + core */ ilf->ilf_size = 2; /* format + core */
xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format));
xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, xfs_inode_item_format_core(ip, lv, &vecp);
&ip->i_d,
xfs_icdinode_size(ip->i_d.di_version));
xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp);
if (XFS_IFORK_Q(ip)) { if (XFS_IFORK_Q(ip)) {
xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp); xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp);

View File

@ -114,7 +114,7 @@ xfs_find_handle(
handle.ha_fid.fid_len = sizeof(xfs_fid_t) - handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
sizeof(handle.ha_fid.fid_len); sizeof(handle.ha_fid.fid_len);
handle.ha_fid.fid_pad = 0; handle.ha_fid.fid_pad = 0;
handle.ha_fid.fid_gen = ip->i_d.di_gen; handle.ha_fid.fid_gen = inode->i_generation;
handle.ha_fid.fid_ino = ip->i_ino; handle.ha_fid.fid_ino = ip->i_ino;
hsize = XFS_HSIZE(handle); hsize = XFS_HSIZE(handle);
@ -963,7 +963,7 @@ xfs_set_diflags(
di_flags |= XFS_DIFLAG_NODEFRAG; di_flags |= XFS_DIFLAG_NODEFRAG;
if (xflags & FS_XFLAG_FILESTREAM) if (xflags & FS_XFLAG_FILESTREAM)
di_flags |= XFS_DIFLAG_FILESTREAM; di_flags |= XFS_DIFLAG_FILESTREAM;
if (S_ISDIR(ip->i_d.di_mode)) { if (S_ISDIR(VFS_I(ip)->i_mode)) {
if (xflags & FS_XFLAG_RTINHERIT) if (xflags & FS_XFLAG_RTINHERIT)
di_flags |= XFS_DIFLAG_RTINHERIT; di_flags |= XFS_DIFLAG_RTINHERIT;
if (xflags & FS_XFLAG_NOSYMLINKS) if (xflags & FS_XFLAG_NOSYMLINKS)
@ -972,7 +972,7 @@ xfs_set_diflags(
di_flags |= XFS_DIFLAG_EXTSZINHERIT; di_flags |= XFS_DIFLAG_EXTSZINHERIT;
if (xflags & FS_XFLAG_PROJINHERIT) if (xflags & FS_XFLAG_PROJINHERIT)
di_flags |= XFS_DIFLAG_PROJINHERIT; di_flags |= XFS_DIFLAG_PROJINHERIT;
} else if (S_ISREG(ip->i_d.di_mode)) { } else if (S_ISREG(VFS_I(ip)->i_mode)) {
if (xflags & FS_XFLAG_REALTIME) if (xflags & FS_XFLAG_REALTIME)
di_flags |= XFS_DIFLAG_REALTIME; di_flags |= XFS_DIFLAG_REALTIME;
if (xflags & FS_XFLAG_EXTSIZE) if (xflags & FS_XFLAG_EXTSIZE)
@ -1128,14 +1128,14 @@ xfs_ioctl_setattr_check_extsize(
{ {
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(ip->i_d.di_mode)) if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(VFS_I(ip)->i_mode))
return -EINVAL; return -EINVAL;
if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) && if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
!S_ISDIR(ip->i_d.di_mode)) !S_ISDIR(VFS_I(ip)->i_mode))
return -EINVAL; return -EINVAL;
if (S_ISREG(ip->i_d.di_mode) && ip->i_d.di_nextents && if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize)) ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
return -EINVAL; return -EINVAL;
@ -1256,9 +1256,9 @@ xfs_ioctl_setattr(
* successful return from chown() * successful return from chown()
*/ */
if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) && if ((VFS_I(ip)->i_mode & (S_ISUID|S_ISGID)) &&
!capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID)) !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
/* Change the ownerships and register project quota modifications */ /* Change the ownerships and register project quota modifications */
if (xfs_get_projid(ip) != fa->fsx_projid) { if (xfs_get_projid(ip) != fa->fsx_projid) {

View File

@ -459,8 +459,8 @@ xfs_vn_getattr(
stat->size = XFS_ISIZE(ip); stat->size = XFS_ISIZE(ip);
stat->dev = inode->i_sb->s_dev; stat->dev = inode->i_sb->s_dev;
stat->mode = ip->i_d.di_mode; stat->mode = inode->i_mode;
stat->nlink = ip->i_d.di_nlink; stat->nlink = inode->i_nlink;
stat->uid = inode->i_uid; stat->uid = inode->i_uid;
stat->gid = inode->i_gid; stat->gid = inode->i_gid;
stat->ino = ip->i_ino; stat->ino = ip->i_ino;
@ -506,9 +506,6 @@ xfs_setattr_mode(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ip->i_d.di_mode &= S_IFMT;
ip->i_d.di_mode |= mode & ~S_IFMT;
inode->i_mode &= S_IFMT; inode->i_mode &= S_IFMT;
inode->i_mode |= mode & ~S_IFMT; inode->i_mode |= mode & ~S_IFMT;
} }
@ -522,21 +519,12 @@ xfs_setattr_time(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
if (iattr->ia_valid & ATTR_ATIME) { if (iattr->ia_valid & ATTR_ATIME)
inode->i_atime = iattr->ia_atime; inode->i_atime = iattr->ia_atime;
ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec; if (iattr->ia_valid & ATTR_CTIME)
ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
}
if (iattr->ia_valid & ATTR_CTIME) {
inode->i_ctime = iattr->ia_ctime; inode->i_ctime = iattr->ia_ctime;
ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec; if (iattr->ia_valid & ATTR_MTIME)
ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
}
if (iattr->ia_valid & ATTR_MTIME) {
inode->i_mtime = iattr->ia_mtime; inode->i_mtime = iattr->ia_mtime;
ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
}
} }
int int
@ -661,9 +649,9 @@ xfs_setattr_nonsize(
* The set-user-ID and set-group-ID bits of a file will be * The set-user-ID and set-group-ID bits of a file will be
* cleared upon successful return from chown() * cleared upon successful return from chown()
*/ */
if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) && if ((inode->i_mode & (S_ISUID|S_ISGID)) &&
!capable(CAP_FSETID)) !capable(CAP_FSETID))
ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); inode->i_mode &= ~(S_ISUID|S_ISGID);
/* /*
* Change the ownerships and register quota modifications * Change the ownerships and register quota modifications
@ -773,7 +761,7 @@ xfs_setattr_size(
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL));
ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT(S_ISREG(inode->i_mode));
ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
@ -991,21 +979,13 @@ xfs_vn_update_time(
} }
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);
if (flags & S_CTIME) { if (flags & S_CTIME)
inode->i_ctime = *now; inode->i_ctime = *now;
ip->i_d.di_ctime.t_sec = (__int32_t)now->tv_sec; if (flags & S_MTIME)
ip->i_d.di_ctime.t_nsec = (__int32_t)now->tv_nsec;
}
if (flags & S_MTIME) {
inode->i_mtime = *now; inode->i_mtime = *now;
ip->i_d.di_mtime.t_sec = (__int32_t)now->tv_sec; if (flags & S_ATIME)
ip->i_d.di_mtime.t_nsec = (__int32_t)now->tv_nsec;
}
if (flags & S_ATIME) {
inode->i_atime = *now; inode->i_atime = *now;
ip->i_d.di_atime.t_sec = (__int32_t)now->tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)now->tv_nsec;
}
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP); xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
return xfs_trans_commit(tp); return xfs_trans_commit(tp);
@ -1232,8 +1212,6 @@ xfs_setup_inode(
/* make the inode look hashed for the writeback code */ /* make the inode look hashed for the writeback code */
hlist_add_fake(&inode->i_hash); hlist_add_fake(&inode->i_hash);
inode->i_mode = ip->i_d.di_mode;
set_nlink(inode, ip->i_d.di_nlink);
inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid); inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid);
inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid); inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid);
@ -1249,14 +1227,7 @@ xfs_setup_inode(
break; break;
} }
inode->i_generation = ip->i_d.di_gen;
i_size_write(inode, ip->i_d.di_size); i_size_write(inode, ip->i_d.di_size);
inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec;
inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
xfs_diflags_to_iflags(inode, ip); xfs_diflags_to_iflags(inode, ip);
ip->d_ops = ip->i_mount->m_nondir_inode_ops; ip->d_ops = ip->i_mount->m_nondir_inode_ops;

View File

@ -57,6 +57,7 @@ xfs_bulkstat_one_int(
{ {
struct xfs_icdinode *dic; /* dinode core info pointer */ struct xfs_icdinode *dic; /* dinode core info pointer */
struct xfs_inode *ip; /* incore inode pointer */ struct xfs_inode *ip; /* incore inode pointer */
struct inode *inode;
struct xfs_bstat *buf; /* return buffer */ struct xfs_bstat *buf; /* return buffer */
int error = 0; /* error value */ int error = 0; /* error value */
@ -77,30 +78,33 @@ xfs_bulkstat_one_int(
ASSERT(ip != NULL); ASSERT(ip != NULL);
ASSERT(ip->i_imap.im_blkno != 0); ASSERT(ip->i_imap.im_blkno != 0);
inode = VFS_I(ip);
dic = &ip->i_d; dic = &ip->i_d;
/* xfs_iget returns the following without needing /* xfs_iget returns the following without needing
* further change. * further change.
*/ */
buf->bs_nlink = dic->di_nlink;
buf->bs_projid_lo = dic->di_projid_lo; buf->bs_projid_lo = dic->di_projid_lo;
buf->bs_projid_hi = dic->di_projid_hi; buf->bs_projid_hi = dic->di_projid_hi;
buf->bs_ino = ino; buf->bs_ino = ino;
buf->bs_mode = dic->di_mode;
buf->bs_uid = dic->di_uid; buf->bs_uid = dic->di_uid;
buf->bs_gid = dic->di_gid; buf->bs_gid = dic->di_gid;
buf->bs_size = dic->di_size; buf->bs_size = dic->di_size;
buf->bs_atime.tv_sec = dic->di_atime.t_sec;
buf->bs_atime.tv_nsec = dic->di_atime.t_nsec; buf->bs_nlink = inode->i_nlink;
buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec; buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
buf->bs_gen = inode->i_generation;
buf->bs_mode = inode->i_mode;
buf->bs_xflags = xfs_ip2xflags(ip); buf->bs_xflags = xfs_ip2xflags(ip);
buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
buf->bs_extents = dic->di_nextents; buf->bs_extents = dic->di_nextents;
buf->bs_gen = dic->di_gen;
memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
buf->bs_dmevmask = dic->di_dmevmask; buf->bs_dmevmask = dic->di_dmevmask;
buf->bs_dmstate = dic->di_dmstate; buf->bs_dmstate = dic->di_dmstate;

View File

@ -2865,7 +2865,7 @@ xfs_recover_inode_owner_change(
return -ENOMEM; return -ENOMEM;
/* instantiate the inode */ /* instantiate the inode */
xfs_dinode_from_disk(&ip->i_d, dip); xfs_inode_from_disk(ip, dip);
ASSERT(ip->i_d.di_version >= 3); ASSERT(ip->i_d.di_version >= 3);
error = xfs_iformat_fork(ip, dip); error = xfs_iformat_fork(ip, dip);
@ -2911,7 +2911,7 @@ xlog_recover_inode_pass2(
int error; int error;
int attr_index; int attr_index;
uint fields; uint fields;
xfs_icdinode_t *dicp; struct xfs_log_dinode *ldip;
uint isize; uint isize;
int need_free = 0; int need_free = 0;
@ -2964,8 +2964,8 @@ xlog_recover_inode_pass2(
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out_release; goto out_release;
} }
dicp = item->ri_buf[1].i_addr; ldip = item->ri_buf[1].i_addr;
if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { if (unlikely(ldip->di_magic != XFS_DINODE_MAGIC)) {
xfs_alert(mp, xfs_alert(mp,
"%s: Bad inode log record, rec ptr 0x%p, ino %Ld", "%s: Bad inode log record, rec ptr 0x%p, ino %Ld",
__func__, item, in_f->ilf_ino); __func__, item, in_f->ilf_ino);
@ -3001,13 +3001,13 @@ xlog_recover_inode_pass2(
* to skip replay when the on disk inode is newer than the log one * to skip replay when the on disk inode is newer than the log one
*/ */
if (!xfs_sb_version_hascrc(&mp->m_sb) && if (!xfs_sb_version_hascrc(&mp->m_sb) &&
dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) { ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
/* /*
* Deal with the wrap case, DI_MAX_FLUSH is less * Deal with the wrap case, DI_MAX_FLUSH is less
* than smaller numbers * than smaller numbers
*/ */
if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH && if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
/* do nothing */ /* do nothing */
} else { } else {
trace_xfs_log_recover_inode_skip(log, in_f); trace_xfs_log_recover_inode_skip(log, in_f);
@ -3017,13 +3017,13 @@ xlog_recover_inode_pass2(
} }
/* Take the opportunity to reset the flush iteration count */ /* Take the opportunity to reset the flush iteration count */
dicp->di_flushiter = 0; ldip->di_flushiter = 0;
if (unlikely(S_ISREG(dicp->di_mode))) { if (unlikely(S_ISREG(ldip->di_mode))) {
if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
(dicp->di_format != XFS_DINODE_FMT_BTREE)) { (ldip->di_format != XFS_DINODE_FMT_BTREE)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
XFS_ERRLEVEL_LOW, mp, dicp); XFS_ERRLEVEL_LOW, mp, ldip);
xfs_alert(mp, xfs_alert(mp,
"%s: Bad regular inode log record, rec ptr 0x%p, " "%s: Bad regular inode log record, rec ptr 0x%p, "
"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
@ -3031,12 +3031,12 @@ xlog_recover_inode_pass2(
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out_release; goto out_release;
} }
} else if (unlikely(S_ISDIR(dicp->di_mode))) { } else if (unlikely(S_ISDIR(ldip->di_mode))) {
if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
(dicp->di_format != XFS_DINODE_FMT_BTREE) && (ldip->di_format != XFS_DINODE_FMT_BTREE) &&
(dicp->di_format != XFS_DINODE_FMT_LOCAL)) { (ldip->di_format != XFS_DINODE_FMT_LOCAL)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
XFS_ERRLEVEL_LOW, mp, dicp); XFS_ERRLEVEL_LOW, mp, ldip);
xfs_alert(mp, xfs_alert(mp,
"%s: Bad dir inode log record, rec ptr 0x%p, " "%s: Bad dir inode log record, rec ptr 0x%p, "
"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
@ -3045,32 +3045,32 @@ xlog_recover_inode_pass2(
goto out_release; goto out_release;
} }
} }
if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ if (unlikely(ldip->di_nextents + ldip->di_anextents > ldip->di_nblocks)){
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
XFS_ERRLEVEL_LOW, mp, dicp); XFS_ERRLEVEL_LOW, mp, ldip);
xfs_alert(mp, xfs_alert(mp,
"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
"dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
__func__, item, dip, bp, in_f->ilf_ino, __func__, item, dip, bp, in_f->ilf_ino,
dicp->di_nextents + dicp->di_anextents, ldip->di_nextents + ldip->di_anextents,
dicp->di_nblocks); ldip->di_nblocks);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out_release; goto out_release;
} }
if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { if (unlikely(ldip->di_forkoff > mp->m_sb.sb_inodesize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
XFS_ERRLEVEL_LOW, mp, dicp); XFS_ERRLEVEL_LOW, mp, ldip);
xfs_alert(mp, xfs_alert(mp,
"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
"dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,
item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); item, dip, bp, in_f->ilf_ino, ldip->di_forkoff);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out_release; goto out_release;
} }
isize = xfs_icdinode_size(dicp->di_version); isize = xfs_log_dinode_size(ldip->di_version);
if (unlikely(item->ri_buf[1].i_len > isize)) { if (unlikely(item->ri_buf[1].i_len > isize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
XFS_ERRLEVEL_LOW, mp, dicp); XFS_ERRLEVEL_LOW, mp, ldip);
xfs_alert(mp, xfs_alert(mp,
"%s: Bad inode log record length %d, rec ptr 0x%p", "%s: Bad inode log record length %d, rec ptr 0x%p",
__func__, item->ri_buf[1].i_len, item); __func__, item->ri_buf[1].i_len, item);
@ -3078,8 +3078,8 @@ xlog_recover_inode_pass2(
goto out_release; goto out_release;
} }
/* The core is in in-core format */ /* recover the log dinode inode into the on disk inode */
xfs_dinode_to_disk(dip, dicp); xfs_log_dinode_to_disk(ldip, dip);
/* the rest is in on-disk format */ /* the rest is in on-disk format */
if (item->ri_buf[1].i_len > isize) { if (item->ri_buf[1].i_len > isize) {
@ -4409,8 +4409,8 @@ xlog_recover_process_one_iunlink(
if (error) if (error)
goto fail_iput; goto fail_iput;
ASSERT(ip->i_d.di_nlink == 0); ASSERT(VFS_I(ip)->i_nlink == 0);
ASSERT(ip->i_d.di_mode != 0); ASSERT(VFS_I(ip)->i_mode != 0);
/* setup for the next pass */ /* setup for the next pass */
agino = be32_to_cpu(dip->di_next_unlinked); agino = be32_to_cpu(dip->di_next_unlinked);

View File

@ -865,7 +865,7 @@ xfs_mountfs(
ASSERT(rip != NULL); ASSERT(rip != NULL);
if (unlikely(!S_ISDIR(rip->i_d.di_mode))) { if (unlikely(!S_ISDIR(VFS_I(rip)->i_mode))) {
xfs_warn(mp, "corrupted root inode %llu: not a directory", xfs_warn(mp, "corrupted root inode %llu: not a directory",
(unsigned long long)rip->i_ino); (unsigned long long)rip->i_ino);
xfs_iunlock(rip, XFS_ILOCK_EXCL); xfs_iunlock(rip, XFS_ILOCK_EXCL);

View File

@ -1272,7 +1272,7 @@ xfs_rtpick_extent(
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime; seqp = (__uint64_t *)&VFS_I(mp->m_rbmip)->i_atime;
if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
*seqp = 0; *seqp = 0;

View File

@ -75,18 +75,10 @@ xfs_trans_ichgtime(
tv = current_fs_time(inode->i_sb); tv = current_fs_time(inode->i_sb);
if ((flags & XFS_ICHGTIME_MOD) && if (flags & XFS_ICHGTIME_MOD)
!timespec_equal(&inode->i_mtime, &tv)) {
inode->i_mtime = tv; inode->i_mtime = tv;
ip->i_d.di_mtime.t_sec = tv.tv_sec; if (flags & XFS_ICHGTIME_CHG)
ip->i_d.di_mtime.t_nsec = tv.tv_nsec;
}
if ((flags & XFS_ICHGTIME_CHG) &&
!timespec_equal(&inode->i_ctime, &tv)) {
inode->i_ctime = tv; inode->i_ctime = tv;
ip->i_d.di_ctime.t_sec = tv.tv_sec;
ip->i_d.di_ctime.t_nsec = tv.tv_nsec;
}
} }
/* /*
@ -125,7 +117,7 @@ xfs_trans_log_inode(
*/ */
if (!(ip->i_itemp->ili_item.li_desc->lid_flags & XFS_LID_DIRTY) && if (!(ip->i_itemp->ili_item.li_desc->lid_flags & XFS_LID_DIRTY) &&
IS_I_VERSION(VFS_I(ip))) { IS_I_VERSION(VFS_I(ip))) {
ip->i_d.di_changecount = ++VFS_I(ip)->i_version; VFS_I(ip)->i_version++;
flags |= XFS_ILOG_CORE; flags |= XFS_ILOG_CORE;
} }