From b43a0f60a61e8e0adea6b1b9adc9a97600fc2f00 Mon Sep 17 00:00:00 2001
From: Kent Overstreet <kent.overstreet@gmail.com>
Date: Wed, 25 Sep 2019 16:19:52 -0400
Subject: [PATCH] bcachefs: Cleanup i_nlink handling

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
 fs/bcachefs/fs.c    | 22 ++++------------------
 fs/bcachefs/fs.h    |  5 -----
 fs/bcachefs/fsck.c  | 13 ++-----------
 fs/bcachefs/inode.h | 43 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 0ba498505b07..b9a20bb19b58 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -131,9 +131,7 @@ void bch2_inode_update_after_write(struct bch_fs *c,
 				   struct bch_inode_unpacked *bi,
 				   unsigned fields)
 {
-	set_nlink(&inode->v, bi->bi_flags & BCH_INODE_UNLINKED
-		  ? 0
-		  : bi->bi_nlink + nlink_bias(inode->v.i_mode));
+	set_nlink(&inode->v, bch2_inode_nlink_get(bi));
 	i_uid_write(&inode->v, bi->bi_uid);
 	i_gid_write(&inode->v, bi->bi_gid);
 	inode->v.i_mode	= bi->bi_mode;
@@ -552,12 +550,7 @@ static int inode_update_for_link_fn(struct bch_inode_info *inode,
 	struct bch_fs *c = inode->v.i_sb->s_fs_info;
 
 	bi->bi_ctime = bch2_current_time(c);
-
-	if (bi->bi_flags & BCH_INODE_UNLINKED)
-		bi->bi_flags &= ~BCH_INODE_UNLINKED;
-	else
-		bi->bi_nlink++;
-
+	bch2_inode_nlink_inc(bi);
 	return 0;
 }
 
@@ -640,11 +633,7 @@ static int inode_update_for_unlink_fn(struct bch_inode_info *inode,
 	struct bch_fs *c = inode->v.i_sb->s_fs_info;
 
 	bi->bi_ctime = bch2_current_time(c);
-	if (bi->bi_nlink)
-		bi->bi_nlink--;
-	else
-		bi->bi_flags |= BCH_INODE_UNLINKED;
-
+	bch2_inode_nlink_dec(bi);
 	return 0;
 }
 
@@ -815,10 +804,7 @@ static int inode_update_for_rename_fn(struct bch_inode_info *inode,
 		BUG_ON(bi->bi_nlink &&
 		       S_ISDIR(info->dst_inode->v.i_mode));
 
-		if (bi->bi_nlink)
-			bi->bi_nlink--;
-		else
-			bi->bi_flags |= BCH_INODE_UNLINKED;
+		bch2_inode_nlink_dec(bi);
 	}
 
 	if (inode == info->src_dir ||
diff --git a/fs/bcachefs/fs.h b/fs/bcachefs/fs.h
index 6edf5dd803f0..04ac5b4129a4 100644
--- a/fs/bcachefs/fs.h
+++ b/fs/bcachefs/fs.h
@@ -109,11 +109,6 @@ static inline u8 mode_to_type(umode_t mode)
 	return (mode >> 12) & 15;
 }
 
-static inline unsigned nlink_bias(umode_t mode)
-{
-	return S_ISDIR(mode) ? 2 : 1;
-}
-
 static inline bool inode_attr_changing(struct bch_inode_info *dir,
 				struct bch_inode_info *inode,
 				enum inode_opt_id id)
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 50a7d8c1faba..162563b809fb 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -1116,9 +1116,7 @@ static int check_inode_nlink(struct bch_fs *c,
 			     struct nlink *link,
 			     bool *do_update)
 {
-	u32 i_nlink = u->bi_flags & BCH_INODE_UNLINKED
-		? 0
-		: u->bi_nlink + nlink_bias(u->bi_mode);
+	u32 i_nlink = bch2_inode_nlink_get(u);
 	u32 real_i_nlink =
 		link->count * nlink_bias(u->bi_mode) +
 		link->dir_count;
@@ -1197,14 +1195,7 @@ static int check_inode_nlink(struct bch_fs *c,
 			    u->bi_inum, i_nlink, real_i_nlink);
 set_i_nlink:
 	if (i_nlink != real_i_nlink) {
-		if (real_i_nlink) {
-			u->bi_nlink = real_i_nlink - nlink_bias(u->bi_mode);
-			u->bi_flags &= ~BCH_INODE_UNLINKED;
-		} else {
-			u->bi_nlink = 0;
-			u->bi_flags |= BCH_INODE_UNLINKED;
-		}
-
+		bch2_inode_nlink_set(u, real_i_nlink);
 		*do_update = true;
 	}
 fsck_err:
diff --git a/fs/bcachefs/inode.h b/fs/bcachefs/inode.h
index af0c355f2f04..e88ec78071bd 100644
--- a/fs/bcachefs/inode.h
+++ b/fs/bcachefs/inode.h
@@ -103,6 +103,49 @@ static inline u64 bch2_inode_opt_get(struct bch_inode_unpacked *inode,
 	}
 }
 
+/* i_nlink: */
+
+static inline unsigned nlink_bias(umode_t mode)
+{
+	return S_ISDIR(mode) ? 2 : 1;
+}
+
+static inline void bch2_inode_nlink_inc(struct bch_inode_unpacked *bi)
+{
+	if (bi->bi_flags & BCH_INODE_UNLINKED)
+		bi->bi_flags &= ~BCH_INODE_UNLINKED;
+	else
+		bi->bi_nlink++;
+}
+
+static inline void bch2_inode_nlink_dec(struct bch_inode_unpacked *bi)
+{
+	BUG_ON(bi->bi_flags & BCH_INODE_UNLINKED);
+	if (bi->bi_nlink)
+		bi->bi_nlink--;
+	else
+		bi->bi_flags |= BCH_INODE_UNLINKED;
+}
+
+static inline unsigned bch2_inode_nlink_get(struct bch_inode_unpacked *bi)
+{
+	return bi->bi_flags & BCH_INODE_UNLINKED
+		  ? 0
+		  : bi->bi_nlink + nlink_bias(bi->bi_mode);
+}
+
+static inline void bch2_inode_nlink_set(struct bch_inode_unpacked *bi,
+					unsigned nlink)
+{
+	if (nlink) {
+		bi->bi_nlink = nlink - nlink_bias(bi->bi_mode);
+		bi->bi_flags &= ~BCH_INODE_UNLINKED;
+	} else {
+		bi->bi_nlink = 0;
+		bi->bi_flags |= BCH_INODE_UNLINKED;
+	}
+}
+
 #ifdef CONFIG_BCACHEFS_DEBUG
 void bch2_inode_pack_test(void);
 #else
-- 
2.30.9