Commit 54d7b5c1 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner

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: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 50997470
...@@ -210,12 +210,12 @@ xfs_inode_from_disk( ...@@ -210,12 +210,12 @@ xfs_inode_from_disk(
* minimum inode version format we support in the rest of the code. * minimum inode version format we support in the rest of the code.
*/ */
if (to->di_version == 1) { 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_lo = 0;
to->di_projid_hi = 0; to->di_projid_hi = 0;
to->di_version = 2; to->di_version = 2;
} else { } 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_lo = be16_to_cpu(from->di_projid_lo);
to->di_projid_hi = be16_to_cpu(from->di_projid_hi); to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
} }
...@@ -275,7 +275,6 @@ xfs_inode_to_disk( ...@@ -275,7 +275,6 @@ xfs_inode_to_disk(
to->di_format = from->di_format; to->di_format = from->di_format;
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_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);
...@@ -286,6 +285,7 @@ xfs_inode_to_disk( ...@@ -286,6 +285,7 @@ xfs_inode_to_disk(
to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec); 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_sec = cpu_to_be32(inode->i_ctime.tv_sec);
to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec); 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_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);
......
...@@ -34,7 +34,6 @@ struct xfs_icdinode { ...@@ -34,7 +34,6 @@ struct xfs_icdinode {
__uint16_t di_flushiter; /* incremented on flush */ __uint16_t di_flushiter; /* incremented on flush */
__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 */
__uint16_t di_projid_lo; /* lower part of owner's project 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 */ __uint16_t di_projid_hi; /* higher part of owner's project id */
xfs_fsize_t di_size; /* number of bytes in file */ xfs_fsize_t di_size; /* number of bytes in file */
......
...@@ -148,9 +148,11 @@ xfs_reinit_inode( ...@@ -148,9 +148,11 @@ xfs_reinit_inode(
struct inode *inode) struct inode *inode)
{ {
int error; int error;
uint32_t nlink = inode->i_nlink;
error = inode_init_always(mp->m_super, inode); error = inode_init_always(mp->m_super, inode);
set_nlink(inode, nlink);
return error; return error;
} }
......
...@@ -57,9 +57,9 @@ kmem_zone_t *xfs_inode_zone; ...@@ -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
...@@ -803,7 +803,7 @@ xfs_ialloc( ...@@ -803,7 +803,7 @@ xfs_ialloc(
ip->i_d.di_version = 2; ip->i_d.di_version = 2;
ip->i_d.di_mode = mode; 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_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);
...@@ -1086,35 +1086,24 @@ xfs_dir_ialloc( ...@@ -1086,35 +1086,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;
} }
/* /*
...@@ -1128,8 +1117,6 @@ xfs_bumplink( ...@@ -1128,8 +1117,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;
...@@ -1387,7 +1374,6 @@ xfs_create_tmpfile( ...@@ -1387,7 +1374,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;
...@@ -1486,7 +1472,10 @@ xfs_link( ...@@ -1486,7 +1472,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;
...@@ -1673,7 +1662,7 @@ xfs_release( ...@@ -1673,7 +1662,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)) {
...@@ -1889,7 +1878,7 @@ xfs_inactive( ...@@ -1889,7 +1878,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
...@@ -1946,16 +1935,21 @@ xfs_inactive( ...@@ -1946,16 +1935,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;
...@@ -1965,11 +1959,8 @@ xfs_iunlink( ...@@ -1965,11 +1959,8 @@ xfs_iunlink(
int offset; int offset;
int error; int error;
ASSERT(ip->i_d.di_nlink == 0);
ASSERT(ip->i_d.di_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
* on the list. * on the list.
...@@ -2406,7 +2397,7 @@ xfs_ifree( ...@@ -2406,7 +2397,7 @@ 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(ip->i_d.di_mode));
...@@ -2574,8 +2565,8 @@ xfs_remove( ...@@ -2574,8 +2565,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;
} }
...@@ -3031,7 +3022,7 @@ xfs_rename( ...@@ -3031,7 +3022,7 @@ xfs_rename(
* 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;
} }
...@@ -3138,7 +3129,7 @@ xfs_rename( ...@@ -3138,7 +3129,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;
......
...@@ -405,8 +405,6 @@ int xfs_ifree(struct xfs_trans *, xfs_inode_t *, ...@@ -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 *);
......
...@@ -338,7 +338,6 @@ xfs_inode_to_log_dinode( ...@@ -338,7 +338,6 @@ xfs_inode_to_log_dinode(
to->di_format = from->di_format; to->di_format = from->di_format;
to->di_uid = from->di_uid; to->di_uid = from->di_uid;
to->di_gid = from->di_gid; to->di_gid = from->di_gid;
to->di_nlink = from->di_nlink;
to->di_projid_lo = from->di_projid_lo; to->di_projid_lo = from->di_projid_lo;
to->di_projid_hi = from->di_projid_hi; to->di_projid_hi = from->di_projid_hi;
...@@ -350,6 +349,7 @@ xfs_inode_to_log_dinode( ...@@ -350,6 +349,7 @@ xfs_inode_to_log_dinode(
to->di_mtime.t_nsec = inode->i_mtime.tv_nsec; to->di_mtime.t_nsec = inode->i_mtime.tv_nsec;
to->di_ctime.t_sec = inode->i_ctime.tv_sec; to->di_ctime.t_sec = inode->i_ctime.tv_sec;
to->di_ctime.t_nsec = inode->i_ctime.tv_nsec; to->di_ctime.t_nsec = inode->i_ctime.tv_nsec;
to->di_nlink = inode->i_nlink;
to->di_size = from->di_size; to->di_size = from->di_size;
to->di_nblocks = from->di_nblocks; to->di_nblocks = from->di_nblocks;
......
...@@ -460,7 +460,7 @@ xfs_vn_getattr( ...@@ -460,7 +460,7 @@ 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 = ip->i_d.di_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;
...@@ -1216,7 +1216,6 @@ xfs_setup_inode( ...@@ -1216,7 +1216,6 @@ xfs_setup_inode(
hlist_add_fake(&inode->i_hash); hlist_add_fake(&inode->i_hash);
inode->i_mode = ip->i_d.di_mode; 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);
......
...@@ -85,7 +85,6 @@ xfs_bulkstat_one_int( ...@@ -85,7 +85,6 @@ xfs_bulkstat_one_int(
/* 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;
...@@ -94,6 +93,7 @@ xfs_bulkstat_one_int( ...@@ -94,6 +93,7 @@ xfs_bulkstat_one_int(
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_nlink = inode->i_nlink;
buf->bs_atime.tv_sec = inode->i_atime.tv_sec; buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec; buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec; buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
......
...@@ -4337,7 +4337,7 @@ xlog_recover_process_one_iunlink( ...@@ -4337,7 +4337,7 @@ 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(ip->i_d.di_mode != 0);
/* setup for the next pass */ /* setup for the next pass */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment