From 3987848c7c2be112e03c82d03821b044f1c0edec Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 9 Feb 2016 16:54:58 +1100 Subject: xfs: remove timestamps from incore inode The struct xfs_inode has two copies of the current timestamps in it, one in the vfs inode and one in the struct xfs_icdinode. Now that we no longer log the struct xfs_icdinode directly, we don't need to keep the timestamps in this structure. instead we can copy them straight out of the VFS inode when formatting the inode log item or the on-disk inode. This reduces the struct xfs_inode in size by 24 bytes. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 76b71a1c6c32..cd27c6d56dfc 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -522,21 +522,12 @@ xfs_setattr_time( 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; - ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec; - ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec; - } - if (iattr->ia_valid & ATTR_CTIME) { + if (iattr->ia_valid & ATTR_CTIME) inode->i_ctime = iattr->ia_ctime; - ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec; - ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec; - } - if (iattr->ia_valid & ATTR_MTIME) { + if (iattr->ia_valid & ATTR_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 @@ -991,21 +982,13 @@ xfs_vn_update_time( } xfs_ilock(ip, XFS_ILOCK_EXCL); - if (flags & S_CTIME) { + if (flags & S_CTIME) inode->i_ctime = *now; - ip->i_d.di_ctime.t_sec = (__int32_t)now->tv_sec; - ip->i_d.di_ctime.t_nsec = (__int32_t)now->tv_nsec; - } - if (flags & S_MTIME) { + if (flags & S_MTIME) inode->i_mtime = *now; - ip->i_d.di_mtime.t_sec = (__int32_t)now->tv_sec; - ip->i_d.di_mtime.t_nsec = (__int32_t)now->tv_nsec; - } - if (flags & S_ATIME) { + if (flags & S_ATIME) 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_log_inode(tp, ip, XFS_ILOG_TIMESTAMP); return xfs_trans_commit(tp); @@ -1251,12 +1234,6 @@ xfs_setup_inode( inode->i_generation = ip->i_d.di_gen; 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); ip->d_ops = ip->i_mount->m_nondir_inode_ops; -- cgit v1.2.3-70-g09d2 From 54d7b5c1d03e9711cce2d72237d5b3f5c87431f4 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 9 Feb 2016 16:54:58 +1100 Subject: xfs: use vfs inode nlink field everywhere The VFS tracks the inode nlink just like the xfs_icdinode. We can remove the variable from the icdinode and use the VFS inode variable everywhere, reducing the size of the xfs_icdinode by a further 4 bytes. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_inode_buf.c | 6 ++-- fs/xfs/libxfs/xfs_inode_buf.h | 1 - fs/xfs/xfs_icache.c | 2 ++ fs/xfs/xfs_inode.c | 77 +++++++++++++++++++------------------------ fs/xfs/xfs_inode.h | 2 -- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_iops.c | 3 +- fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_log_recover.c | 2 +- 9 files changed, 43 insertions(+), 54 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index fe8f4f349b37..cc509c1af75e 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -210,12 +210,12 @@ xfs_inode_from_disk( * minimum inode version format we support in the rest of the code. */ if (to->di_version == 1) { - to->di_nlink = be16_to_cpu(from->di_onlink); + set_nlink(inode, be16_to_cpu(from->di_onlink)); to->di_projid_lo = 0; to->di_projid_hi = 0; to->di_version = 2; } else { - to->di_nlink = be32_to_cpu(from->di_nlink); + 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); } @@ -275,7 +275,6 @@ xfs_inode_to_disk( 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_nlink = cpu_to_be32(from->di_nlink); to->di_projid_lo = cpu_to_be16(from->di_projid_lo); to->di_projid_hi = cpu_to_be16(from->di_projid_hi); @@ -286,6 +285,7 @@ xfs_inode_to_disk( 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_size = cpu_to_be64(from->di_size); to->di_nblocks = cpu_to_be64(from->di_nblocks); diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h index 73ba1d8ffac2..320b72344270 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.h +++ b/fs/xfs/libxfs/xfs_inode_buf.h @@ -34,7 +34,6 @@ struct xfs_icdinode { __uint16_t di_flushiter; /* incremented on flush */ __uint32_t di_uid; /* owner's user id */ __uint32_t di_gid; /* owner's group id */ - __uint32_t di_nlink; /* number of links to file */ __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 */ diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 9ca2865575ab..4c184f70d43c 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -148,9 +148,11 @@ xfs_reinit_inode( struct inode *inode) { int error; + uint32_t nlink = inode->i_nlink; error = inode_init_always(mp->m_super, inode); + set_nlink(inode, nlink); return error; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 7d9c514fd231..18b3bc0c211a 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -57,9 +57,9 @@ kmem_zone_t *xfs_inode_zone; */ #define XFS_ITRUNC_MAX_EXTENTS 2 -STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); - -STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_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(struct xfs_trans *, struct xfs_inode *); /* * helper function to extract extent size hint from inode @@ -803,7 +803,7 @@ xfs_ialloc( ip->i_d.di_version = 2; ip->i_d.di_mode = mode; - ip->i_d.di_nlink = nlink; + set_nlink(inode, nlink); ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid()); ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid()); xfs_set_projid(ip, prid); @@ -1086,35 +1086,24 @@ xfs_dir_ialloc( } /* - * Decrement the link count on an inode & log the change. - * If this causes the link count to go to zero, initiate the - * logging activity required to truncate a file. + * Decrement the link count on an inode & log the change. If this causes the + * link count to go to zero, move the inode to AGI unlinked list so that it can + * be freed when the last active reference goes away via xfs_inactive(). */ int /* error */ xfs_droplink( xfs_trans_t *tp, xfs_inode_t *ip) { - int error; - 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)); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = 0; - if (ip->i_d.di_nlink == 0) { - /* - * We're dropping the last link to this file. - * 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; + if (VFS_I(ip)->i_nlink) + return 0; + + return xfs_iunlink(tp, ip); } /* @@ -1128,8 +1117,6 @@ xfs_bumplink( xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); 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)); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); return 0; @@ -1387,7 +1374,6 @@ xfs_create_tmpfile( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); - ip->i_d.di_nlink--; error = xfs_iunlink(tp, ip); if (error) goto out_trans_cancel; @@ -1486,7 +1472,10 @@ xfs_link( 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); if (error) goto error_return; @@ -1673,7 +1662,7 @@ xfs_release( } } - if (ip->i_d.di_nlink == 0) + if (VFS_I(ip)->i_nlink == 0) return 0; if (xfs_can_free_eofblocks(ip, false)) { @@ -1889,7 +1878,7 @@ xfs_inactive( if (mp->m_flags & XFS_MOUNT_RDONLY) 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 * cache. Post-eof blocks must be freed, lest we end up with @@ -1946,16 +1935,21 @@ xfs_inactive( } /* - * This is called when the inode's link count goes to 0. - * We place the on-disk inode on a list in the AGI. It - * will be pulled from this list when the inode is freed. + * This is called when the inode's link count goes to 0 or we are creating a + * tmpfile via O_TMPFILE. In the case of a tmpfile, @ignore_linkcount will be + * 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_trans_t *tp, - xfs_inode_t *ip) + struct xfs_trans *tp, + struct xfs_inode *ip) { - xfs_mount_t *mp; + xfs_mount_t *mp = tp->t_mountp; xfs_agi_t *agi; xfs_dinode_t *dip; xfs_buf_t *agibp; @@ -1965,11 +1959,8 @@ xfs_iunlink( int offset; int error; - ASSERT(ip->i_d.di_nlink == 0); ASSERT(ip->i_d.di_mode != 0); - mp = tp->t_mountp; - /* * Get the agi buffer first. It ensures lock ordering * on the list. @@ -2406,7 +2397,7 @@ xfs_ifree( struct xfs_icluster xic = { 0 }; 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_anextents == 0); ASSERT(ip->i_d.di_size == 0 || !S_ISREG(ip->i_d.di_mode)); @@ -2574,8 +2565,8 @@ xfs_remove( * If we're removing a directory perform some additional validation. */ if (is_dir) { - ASSERT(ip->i_d.di_nlink >= 2); - if (ip->i_d.di_nlink != 2) { + ASSERT(VFS_I(ip)->i_nlink >= 2); + if (VFS_I(ip)->i_nlink != 2) { error = -ENOTEMPTY; goto out_trans_cancel; } @@ -3031,7 +3022,7 @@ xfs_rename( * Make sure target dir is empty. */ if (!(xfs_dir_isempty(target_ip)) || - (target_ip->i_d.di_nlink > 2)) { + (VFS_I(target_ip)->i_nlink > 2)) { error = -EEXIST; goto out_trans_cancel; } @@ -3138,7 +3129,7 @@ xfs_rename( * intermediate state on disk. */ 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); if (error) goto out_bmap_cancel; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index aef5452b1a90..e74d13d3076b 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -405,8 +405,6 @@ int xfs_ifree(struct xfs_trans *, xfs_inode_t *, struct xfs_bmap_free *); int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *, int, xfs_fsize_t); -int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); - void xfs_iext_realloc(xfs_inode_t *, int, int); void xfs_iunpin_wait(xfs_inode_t *); diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 1e5ecbc45459..193e0bdec340 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -338,7 +338,6 @@ xfs_inode_to_log_dinode( to->di_format = from->di_format; 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; @@ -350,6 +349,7 @@ xfs_inode_to_log_dinode( 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_size = from->di_size; to->di_nblocks = from->di_nblocks; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index cd27c6d56dfc..8982e56e07c4 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -460,7 +460,7 @@ xfs_vn_getattr( stat->size = XFS_ISIZE(ip); stat->dev = inode->i_sb->s_dev; stat->mode = ip->i_d.di_mode; - stat->nlink = ip->i_d.di_nlink; + stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; stat->ino = ip->i_ino; @@ -1216,7 +1216,6 @@ xfs_setup_inode( 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_gid = xfs_gid_to_kgid(ip->i_d.di_gid); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 2acda42319f5..cfb65273d361 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -85,7 +85,6 @@ xfs_bulkstat_one_int( /* xfs_iget returns the following without needing * further change. */ - buf->bs_nlink = dic->di_nlink; buf->bs_projid_lo = dic->di_projid_lo; buf->bs_projid_hi = dic->di_projid_hi; buf->bs_ino = ino; @@ -94,6 +93,7 @@ xfs_bulkstat_one_int( buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; + buf->bs_nlink = inode->i_nlink; buf->bs_atime.tv_sec = inode->i_atime.tv_sec; buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec; buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 4b79cf006589..611c25cdb15c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4337,7 +4337,7 @@ xlog_recover_process_one_iunlink( if (error) goto fail_iput; - ASSERT(ip->i_d.di_nlink == 0); + ASSERT(VFS_I(ip)->i_nlink == 0); ASSERT(ip->i_d.di_mode != 0); /* setup for the next pass */ -- cgit v1.2.3-70-g09d2 From 9e9a2674e43353f650ecd19a54eba028eafff82e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 9 Feb 2016 16:54:58 +1100 Subject: xfs: move inode generation count to VFS inode Pull another 4 bytes out of the xfs_icdinode. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_inode_buf.c | 8 ++++---- fs/xfs/libxfs/xfs_inode_buf.h | 1 - fs/xfs/xfs_export.c | 2 +- fs/xfs/xfs_icache.c | 2 ++ fs/xfs/xfs_inode.c | 5 +---- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_ioctl.c | 2 +- fs/xfs/xfs_iops.c | 1 - fs/xfs/xfs_itable.c | 2 +- 9 files changed, 11 insertions(+), 14 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index cc509c1af75e..9113a8d0f148 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -237,6 +237,7 @@ xfs_inode_from_disk( 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); to->di_size = be64_to_cpu(from->di_size); to->di_nblocks = be64_to_cpu(from->di_nblocks); @@ -248,7 +249,6 @@ xfs_inode_from_disk( to->di_dmevmask = be32_to_cpu(from->di_dmevmask); to->di_dmstate = be16_to_cpu(from->di_dmstate); to->di_flags = be16_to_cpu(from->di_flags); - to->di_gen = be32_to_cpu(from->di_gen); if (to->di_version == 3) { to->di_changecount = be64_to_cpu(from->di_changecount); @@ -286,6 +286,7 @@ xfs_inode_to_disk( 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_size = cpu_to_be64(from->di_size); to->di_nblocks = cpu_to_be64(from->di_nblocks); @@ -297,7 +298,6 @@ xfs_inode_to_disk( 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); - to->di_gen = cpu_to_be32(from->di_gen); if (from->di_version == 3) { to->di_changecount = cpu_to_be64(from->di_changecount); @@ -443,7 +443,7 @@ xfs_iread( !(mp->m_flags & XFS_MOUNT_IKEEP)) { /* initialise the on-disk inode core */ memset(&ip->i_d, 0, sizeof(ip->i_d)); - ip->i_d.di_gen = prandom_u32(); + VFS_I(ip)->i_generation = prandom_u32(); if (xfs_sb_version_hascrc(&mp->m_sb)) ip->i_d.di_version = 3; else @@ -491,7 +491,7 @@ xfs_iread( * that xfs_ialloc won't overwrite or relies on being correct. */ 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); /* diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h index 320b72344270..29fd9f1cf54b 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.h +++ b/fs/xfs/libxfs/xfs_inode_buf.h @@ -46,7 +46,6 @@ struct xfs_icdinode { __uint32_t di_dmevmask; /* DMIG event mask */ __uint16_t di_dmstate; /* DMIG state info */ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ - __uint32_t di_gen; /* generation number */ __uint64_t di_changecount; /* number of attribute changes */ __uint64_t di_flags2; /* more random flags */ diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 652cd3c5b58c..2816d42507bc 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -152,7 +152,7 @@ xfs_nfs_get_inode( return ERR_PTR(error); } - if (ip->i_d.di_gen != generation) { + if (VFS_I(ip)->i_generation != generation) { IRELE(ip); return ERR_PTR(-ESTALE); } diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 4c184f70d43c..6401e3c07d3a 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -149,10 +149,12 @@ xfs_reinit_inode( { int error; uint32_t nlink = inode->i_nlink; + uint32_t generation = inode->i_generation; error = inode_init_always(mp->m_super, inode); set_nlink(inode, nlink); + inode->i_generation = generation; return error; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 18b3bc0c211a..dfc5b18c8cc2 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -835,9 +835,6 @@ xfs_ialloc( inode->i_atime = tv; inode->i_ctime = tv; - /* - * di_gen will have been taken care of in xfs_iread. - */ ip->i_d.di_extsize = 0; ip->i_d.di_dmevmask = 0; ip->i_d.di_dmstate = 0; @@ -2424,7 +2421,7 @@ xfs_ifree( * Bump the generation count so no one will be confused * by reincarnations of this inode. */ - ip->i_d.di_gen++; + VFS_I(ip)->i_generation++; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); if (xic.deleted) diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 193e0bdec340..6367780b8abb 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -350,6 +350,7 @@ xfs_inode_to_log_dinode( 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_size = from->di_size; to->di_nblocks = from->di_nblocks; @@ -361,7 +362,6 @@ xfs_inode_to_log_dinode( 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; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 478d04e07f95..cdd6c3156d53 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -114,7 +114,7 @@ xfs_find_handle( handle.ha_fid.fid_len = sizeof(xfs_fid_t) - sizeof(handle.ha_fid.fid_len); 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; hsize = XFS_HSIZE(handle); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 8982e56e07c4..a4daa3fd3ae9 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1231,7 +1231,6 @@ xfs_setup_inode( break; } - inode->i_generation = ip->i_d.di_gen; i_size_write(inode, ip->i_d.di_size); xfs_diflags_to_iflags(inode, ip); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index cfb65273d361..6162e65f10b6 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -100,11 +100,11 @@ xfs_bulkstat_one_int( 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_xflags = xfs_ip2xflags(ip); buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; buf->bs_extents = dic->di_nextents; - buf->bs_gen = dic->di_gen; memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); buf->bs_dmevmask = dic->di_dmevmask; buf->bs_dmstate = dic->di_dmstate; -- cgit v1.2.3-70-g09d2 From c19b3b05ae440de50fffe2ac2a9b27392a7448e9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 9 Feb 2016 16:54:58 +1100 Subject: xfs: mode di_mode to vfs inode Move the di_mode value from the xfs_icdinode to the VFS inode, reducing the xfs_icdinode byte another 2 bytes and collapsing another 2 byte hole in the structure. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_bmap.c | 6 +++--- fs/xfs/libxfs/xfs_dir2.c | 12 +++++------ fs/xfs/libxfs/xfs_inode_buf.c | 8 +++---- fs/xfs/libxfs/xfs_inode_buf.h | 1 - fs/xfs/libxfs/xfs_inode_fork.c | 2 +- fs/xfs/xfs_bmap_util.c | 4 ++-- fs/xfs/xfs_dir2_readdir.c | 2 +- fs/xfs/xfs_file.c | 6 +++--- fs/xfs/xfs_filestream.c | 4 ++-- fs/xfs/xfs_icache.c | 13 ++++++++---- fs/xfs/xfs_inode.c | 48 ++++++++++++++++++++---------------------- fs/xfs/xfs_inode.h | 4 ++-- fs/xfs/xfs_inode_item.c | 2 +- fs/xfs/xfs_ioctl.c | 14 ++++++------ fs/xfs/xfs_iops.c | 12 ++++------- fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_mount.c | 2 +- 18 files changed, 71 insertions(+), 73 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index ef00156f4f96..6a051662d8f9 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -912,7 +912,7 @@ xfs_bmap_local_to_extents( * 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. */ - 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); 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)) return 0; - if (S_ISDIR(ip->i_d.di_mode)) { + if (S_ISDIR(VFS_I(ip)->i_mode)) { memset(&dargs, 0, sizeof(dargs)); dargs.geo = ip->i_mount->m_dir_geo; dargs.dp = ip; @@ -1091,7 +1091,7 @@ xfs_bmap_add_attrfork_local( 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, flags, XFS_DATA_FORK, xfs_symlink_local_to_remote); diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 2fb53a5c0a74..af0f9d171f8a 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -176,7 +176,7 @@ xfs_dir_isempty( { 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. */ return 1; if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) @@ -231,7 +231,7 @@ xfs_dir_init( struct xfs_da_args *args; 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); if (error) return error; @@ -266,7 +266,7 @@ xfs_dir_createname( int rval; int v; /* type-checking value */ - ASSERT(S_ISDIR(dp->i_d.di_mode)); + ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); if (inum) { rval = xfs_dir_ino_validate(tp->t_mountp, inum); if (rval) @@ -364,7 +364,7 @@ xfs_dir_lookup( int v; /* type-checking value */ 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); /* @@ -443,7 +443,7 @@ xfs_dir_removename( int rval; 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); args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); @@ -505,7 +505,7 @@ xfs_dir_replace( int rval; 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); if (rval) diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 05fbefa97fbf..9d9559eb2835 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -202,13 +202,12 @@ xfs_inode_from_disk( struct xfs_icdinode *to = &ip->i_d; struct inode *inode = VFS_I(ip); - to->di_mode = be16_to_cpu(from->di_mode); - 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; @@ -238,6 +237,7 @@ xfs_inode_from_disk( 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_nblocks = be64_to_cpu(from->di_nblocks); @@ -270,7 +270,6 @@ xfs_inode_to_disk( to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); to->di_onlink = 0; - to->di_mode = cpu_to_be16(from->di_mode); to->di_version = from->di_version; to->di_format = from->di_format; to->di_uid = cpu_to_be32(from->di_uid); @@ -287,6 +286,7 @@ xfs_inode_to_disk( 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); @@ -501,7 +501,7 @@ xfs_iread( * the inode is already free and not try to mess * with the uninitialized part of it. */ - ip->i_d.di_mode = 0; + VFS_I(ip)->i_mode = 0; } ASSERT(ip->i_d.di_version >= 2); diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h index c51bd1213c96..7c4dd321b215 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.h +++ b/fs/xfs/libxfs/xfs_inode_buf.h @@ -28,7 +28,6 @@ struct xfs_dinode; * format specific structures at the appropriate time. */ struct xfs_icdinode { - __uint16_t di_mode; /* mode and type of file */ __int8_t di_version; /* inode version */ __int8_t di_format; /* format of di_c data */ __uint16_t di_flushiter; /* incremented on flush */ diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 0defbd02f62d..0bf1c747439d 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -120,7 +120,7 @@ xfs_iformat_fork( return -EFSCORRUPTED; } - switch (ip->i_d.di_mode & S_IFMT) { + switch (VFS_I(ip)->i_mode & S_IFMT) { case S_IFIFO: case S_IFCHR: case S_IFBLK: diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 45ec9e40150c..708775613e55 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -821,7 +821,7 @@ bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force) { /* 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; /* @@ -1726,7 +1726,7 @@ xfs_swap_extents( xfs_lock_two_inodes(ip, tip, XFS_MMAPLOCK_EXCL); /* 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; goto out_unlock; } diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 642d55d10075..93b3ab0c5435 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -665,7 +665,7 @@ xfs_readdir( if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 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); args.dp = dp; diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 52883ac3cf84..f7333fbba5c2 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -156,9 +156,9 @@ xfs_update_prealloc_flags( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); if (!(flags & XFS_PREALLOC_INVISIBLE)) { - ip->i_d.di_mode &= ~S_ISUID; - if (ip->i_d.di_mode & S_IXGRP) - ip->i_d.di_mode &= ~S_ISGID; + VFS_I(ip)->i_mode &= ~S_ISUID; + if (VFS_I(ip)->i_mode & S_IXGRP) + VFS_I(ip)->i_mode &= ~S_ISGID; xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); } diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index c4c130f9bfb6..a51353a1f87f 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -151,7 +151,7 @@ xfs_filestream_pick_ag( xfs_agnumber_t ag, max_ag = NULLAGNUMBER; 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. */ minfree = mp->m_sb.sb_agblocks / 50; @@ -319,7 +319,7 @@ xfs_filestream_lookup_ag( xfs_agnumber_t startag, ag = NULLAGNUMBER; 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); if (!pip) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 30eafad7cf19..bf2d60749278 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -63,6 +63,9 @@ xfs_inode_alloc( return NULL; } + /* VFS doesn't initialise i_mode! */ + VFS_I(ip)->i_mode = 0; + XFS_STATS_INC(mp, vn_active); ASSERT(atomic_read(&ip->i_pincount) == 0); ASSERT(!spin_is_locked(&ip->i_flags_lock)); @@ -98,7 +101,7 @@ void xfs_inode_free( 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_IFDIR: case S_IFLNK: @@ -151,12 +154,14 @@ xfs_reinit_inode( 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; } @@ -211,7 +216,7 @@ xfs_iget_cache_hit( /* * 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; goto out_error; } @@ -321,7 +326,7 @@ xfs_iget_cache_miss( 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; goto out_destroy; } @@ -470,7 +475,7 @@ again: * 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. */ - 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); return 0; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 8a970056a2c4..26bac4ab79a3 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -802,7 +802,7 @@ xfs_ialloc( if (ip->i_d.di_version == 1) ip->i_d.di_version = 2; - ip->i_d.di_mode = mode; + inode->i_mode = mode; set_nlink(inode, nlink); ip->i_d.di_uid = xfs_kuid_to_uid(current_fsuid()); ip->i_d.di_gid = xfs_kgid_to_gid(current_fsgid()); @@ -810,9 +810,8 @@ xfs_ialloc( if (pip && XFS_INHERIT_GID(pip)) { ip->i_d.di_gid = pip->i_d.di_gid; - if ((pip->i_d.di_mode & S_ISGID) && S_ISDIR(mode)) { - ip->i_d.di_mode |= S_ISGID; - } + if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode)) + inode->i_mode |= S_ISGID; } /* @@ -821,10 +820,9 @@ xfs_ialloc( * (and only if the irix_sgid_inherit compatibility variable is set). */ if ((irix_sgid_inherit) && - (ip->i_d.di_mode & S_ISGID) && - (!in_group_p(xfs_gid_to_kgid(ip->i_d.di_gid)))) { - ip->i_d.di_mode &= ~S_ISGID; - } + (inode->i_mode & S_ISGID) && + (!in_group_p(xfs_gid_to_kgid(ip->i_d.di_gid)))) + inode->i_mode &= ~S_ISGID; ip->i_d.di_size = 0; ip->i_d.di_nextents = 0; @@ -1421,7 +1419,7 @@ xfs_link( 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)) return -EIO; @@ -1628,7 +1626,7 @@ xfs_release( xfs_mount_t *mp = ip->i_mount; 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; /* If this is a read-only mount, don't do this (would generate I/O) */ @@ -1863,7 +1861,7 @@ xfs_inactive( * If the inode is already free, then there can be nothing * 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_broot_bytes == 0); return; @@ -1887,7 +1885,7 @@ xfs_inactive( 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_nextents > 0 || ip->i_delayed_blks > 0)) truncate = 1; @@ -1896,7 +1894,7 @@ xfs_inactive( if (error) return; - if (S_ISLNK(ip->i_d.di_mode)) + if (S_ISLNK(VFS_I(ip)->i_mode)) error = xfs_inactive_symlink(ip); else if (truncate) error = xfs_inactive_truncate(ip); @@ -1956,7 +1954,7 @@ xfs_iunlink( int offset; int error; - ASSERT(ip->i_d.di_mode != 0); + ASSERT(VFS_I(ip)->i_mode != 0); /* * Get the agi buffer first. It ensures lock ordering @@ -2397,7 +2395,7 @@ xfs_ifree( ASSERT(VFS_I(ip)->i_nlink == 0); ASSERT(ip->i_d.di_nextents == 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); /* @@ -2411,7 +2409,7 @@ xfs_ifree( if (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_dmevmask = 0; ip->i_d.di_forkoff = 0; /* mark the attr fork not in use */ @@ -2508,7 +2506,7 @@ xfs_remove( { xfs_mount_t *mp = dp->i_mount; 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; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; @@ -2753,7 +2751,7 @@ xfs_cross_rename( if (dp1 != dp2) { 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, dp1->i_ino, first_block, free_list, spaceres); @@ -2761,7 +2759,7 @@ xfs_cross_rename( goto out_trans_abort; /* 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); if (error) goto out_trans_abort; @@ -2780,7 +2778,7 @@ xfs_cross_rename( 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, dp2->i_ino, first_block, free_list, spaceres); @@ -2788,7 +2786,7 @@ xfs_cross_rename( goto out_trans_abort; /* 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); if (error) goto out_trans_abort; @@ -2885,7 +2883,7 @@ xfs_rename( struct xfs_inode *inodes[__XFS_SORT_INODES]; int num_inodes = __XFS_SORT_INODES; 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 error; @@ -3014,7 +3012,7 @@ xfs_rename( * target and source are directories and that target can be * 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. */ @@ -3444,7 +3442,7 @@ xfs_iflush_int( __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip); goto corrupt_out; } - if (S_ISREG(ip->i_d.di_mode)) { + if (S_ISREG(VFS_I(ip)->i_mode)) { if (XFS_TEST_ERROR( (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_BTREE), @@ -3454,7 +3452,7 @@ xfs_iflush_int( __func__, ip->i_ino, ip); 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( (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e74d13d3076b..d6277494e606 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -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) { - if (S_ISREG(ip->i_d.di_mode)) + if (S_ISREG(VFS_I(ip)->i_mode)) return i_size_read(VFS_I(ip)); return ip->i_d.di_size; } @@ -369,7 +369,7 @@ static inline int xfs_isiflocked(struct xfs_inode *ip) */ #define XFS_INHERIT_GID(pip) \ (((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); void xfs_inactive(struct xfs_inode *ip); diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 3415c63bc843..c48b5b18d771 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -333,7 +333,6 @@ xfs_inode_to_log_dinode( to->di_magic = XFS_DINODE_MAGIC; - to->di_mode = from->di_mode; to->di_version = from->di_version; to->di_format = from->di_format; to->di_uid = from->di_uid; @@ -351,6 +350,7 @@ xfs_inode_to_log_dinode( 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; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index cdd6c3156d53..81d6d6218803 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -963,7 +963,7 @@ xfs_set_diflags( di_flags |= XFS_DIFLAG_NODEFRAG; if (xflags & FS_XFLAG_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) di_flags |= XFS_DIFLAG_RTINHERIT; if (xflags & FS_XFLAG_NOSYMLINKS) @@ -972,7 +972,7 @@ xfs_set_diflags( di_flags |= XFS_DIFLAG_EXTSZINHERIT; if (xflags & FS_XFLAG_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) di_flags |= XFS_DIFLAG_REALTIME; if (xflags & FS_XFLAG_EXTSIZE) @@ -1128,14 +1128,14 @@ xfs_ioctl_setattr_check_extsize( { 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; if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) && - !S_ISDIR(ip->i_d.di_mode)) + !S_ISDIR(VFS_I(ip)->i_mode)) 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)) return -EINVAL; @@ -1256,9 +1256,9 @@ xfs_ioctl_setattr( * 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)) - 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 */ if (xfs_get_projid(ip) != fa->fsx_projid) { diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index a4daa3fd3ae9..0d38b1d2c420 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -459,7 +459,7 @@ xfs_vn_getattr( stat->size = XFS_ISIZE(ip); stat->dev = inode->i_sb->s_dev; - stat->mode = ip->i_d.di_mode; + stat->mode = inode->i_mode; stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; @@ -506,9 +506,6 @@ xfs_setattr_mode( 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 |= mode & ~S_IFMT; } @@ -652,9 +649,9 @@ xfs_setattr_nonsize( * The set-user-ID and set-group-ID bits of a file will be * 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)) - ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); + inode->i_mode &= ~(S_ISUID|S_ISGID); /* * Change the ownerships and register quota modifications @@ -764,7 +761,7 @@ xfs_setattr_size( ASSERT(xfs_isilocked(ip, XFS_IOLOCK_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| ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); @@ -1215,7 +1212,6 @@ xfs_setup_inode( /* make the inode look hashed for the writeback code */ hlist_add_fake(&inode->i_hash); - inode->i_mode = ip->i_d.di_mode; inode->i_uid = xfs_uid_to_kuid(ip->i_d.di_uid); inode->i_gid = xfs_gid_to_kgid(ip->i_d.di_gid); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 6162e65f10b6..ce73eb34620d 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -88,7 +88,6 @@ xfs_bulkstat_one_int( buf->bs_projid_lo = dic->di_projid_lo; buf->bs_projid_hi = dic->di_projid_hi; buf->bs_ino = ino; - buf->bs_mode = dic->di_mode; buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; @@ -101,6 +100,7 @@ xfs_bulkstat_one_int( 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_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 611c25cdb15c..bd6f23b952a5 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4338,7 +4338,7 @@ xlog_recover_process_one_iunlink( goto fail_iput; 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 */ agino = be32_to_cpu(dip->di_next_unlinked); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index bb753b359bee..d3061054bad2 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -865,7 +865,7 @@ xfs_mountfs( 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", (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); -- cgit v1.2.3-70-g09d2 From db10c697b40e34ac91bbcdd866e73a3d0bad7780 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 1 Mar 2016 09:41:33 +1100 Subject: xfs: S_DAX is only for regular files Only regular files can use DAX for data operations, so we should restrict setting it on the VFS inode to regular files. Setting it on metadata inodes may cause the VFS to do the wrong thing for such inodes, so avoid potential problems by restricting the scope of the flag to what we know is supported. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Tested-by: Ross Zwisler Signed-off-by: Dave Chinner --- fs/xfs/xfs_iops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 76b71a1c6c32..5d4f9739d4a4 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1205,8 +1205,9 @@ xfs_diflags_to_iflags( inode->i_flags |= S_SYNC; if (flags & XFS_DIFLAG_NOATIME) inode->i_flags |= S_NOATIME; - if (ip->i_mount->m_flags & XFS_MOUNT_DAX || - ip->i_d.di_flags2 & XFS_DIFLAG2_DAX) + if (S_ISREG(inode->i_mode) && + (ip->i_mount->m_flags & XFS_MOUNT_DAX || + ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) inode->i_flags |= S_DAX; } -- cgit v1.2.3-70-g09d2 From 64485437357dfdc9752495b3f496adfc5c816c6f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 1 Mar 2016 09:41:33 +1100 Subject: xfs: XFS_DIFLAG2_DAX limited by PAGE_SIZE If the block size of a filesystem is not at least PAGE_SIZEd, then at this point in time DAX cannot be used due to the fact we can't guarantee extents are page sized or aligned without further work. Hence disallow setting the DAX flag on an inode if the block size is too small. Also, be defensive and check the block size when reading an inode in off disk. In future, we want to allow DAX to work on any filesystem, so this is temporary while we sort of the correct conbination of extent size hints and allocation alignment configurations needed to guarantee page sized and aligned extent allocation for DAX enabled files. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Tested-by: Ross Zwisler Signed-off-by: Dave Chinner --- fs/xfs/xfs_ioctl.c | 12 ++++++++---- fs/xfs/xfs_iops.c | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'fs/xfs/xfs_iops.c') diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 55ec4d44d4ba..388b5b5b67c9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1080,11 +1080,15 @@ xfs_ioctl_setattr_dax_invalidate( /* * It is only valid to set the DAX flag on regular files and - * directories. On directories it serves as an inherit hint. + * directories on filesystems where the block size is equal to the page + * size. On directories it serves as an inherit hint. */ - if ((fa->fsx_xflags & FS_XFLAG_DAX) && - !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) - return -EINVAL; + if (fa->fsx_xflags & FS_XFLAG_DAX) { + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) + return -EINVAL; + if (ip->i_mount->m_sb.sb_blocksize != PAGE_SIZE) + return -EINVAL; + } /* If the DAX state is not changing, we have nothing to do here. */ if ((fa->fsx_xflags & FS_XFLAG_DAX) && IS_DAX(inode)) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 5d4f9739d4a4..f7386dc10a20 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1206,6 +1206,7 @@ xfs_diflags_to_iflags( if (flags & XFS_DIFLAG_NOATIME) inode->i_flags |= S_NOATIME; if (S_ISREG(inode->i_mode) && + ip->i_mount->m_sb.sb_blocksize == PAGE_SIZE && (ip->i_mount->m_flags & XFS_MOUNT_DAX || ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) inode->i_flags |= S_DAX; -- cgit v1.2.3-70-g09d2