linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dave Kleikamp <shaggy@austin.ibm.com>
To: Oleg Drokin <green@namesys.com>
Cc: "David S. Miller" <davem@redhat.com>,
	szepe@pinerecords.com, mason@suse.com,
	linux-kernel@vger.kernel.org, reiserfs-dev@namesys.com,
	linuxjfs@us.ibm.com
Subject: Re: [reiserfs-dev] Re: [PATCH] sparc32: wrong type of nlink_t
Date: Thu, 5 Sep 2002 12:58:27 -0500	[thread overview]
Message-ID: <200209051258.27366.shaggy@austin.ibm.com> (raw)
In-Reply-To: <20020905201337.A4698@namesys.com>

Here's the JFS patch.  When I first saw this thread I didn't expect that
the result would be increasing the max. number of links.  :^)

Note that I made JFS_LINK_MAX the maximum supported by JFS,
and VFS_LINK_MAX as the number limited by the size of nlink_t.
VFS_LINK_MAX could be moved to fs.h if other file systems are
to use it in the same way.

I borrowed reiserfs's *_INODE_NLINK macros, but made them inline functions.

(I don't usually send patches from kmail.  I hope it doesn't screw up the formatting.)

===== fs/jfs/jfs_filsys.h 1.1 vs edited =====
--- 1.1/fs/jfs/jfs_filsys.h	Fri May 31 08:19:24 2002
+++ edited/fs/jfs/jfs_filsys.h	Thu Sep  5 11:01:55 2002
@@ -125,7 +125,13 @@
 #define MAXBLOCKSIZE		4096
 #define	MAXFILESIZE		((s64)1 << 52)
 
-#define JFS_LINK_MAX		65535	/* nlink_t is unsigned short */
+/*
+ * The max link count in struct inode is limited to the size of nlink_t.
+ * The JFS inode uses an unsigned 32-bit int, so we can really go higher
+ */
+#define JFS_LINK_MAX	0xffffffff	/* real limit */
+#define VFS_LINK_MAX	((((nlink_t) -1) > 0) ? (nlink_t) ~0 : \
+			 ((1u << (sizeof (nlink_t) * 8 - 1)) -1))
 
 /* Minimum number of bytes supported for a JFS partition */
 #define MINJFS			(0x1000000)
===== fs/jfs/jfs_imap.c 1.6 vs edited =====
--- 1.6/fs/jfs/jfs_imap.c	Wed Sep  4 11:11:52 2002
+++ edited/fs/jfs/jfs_imap.c	Thu Sep  5 10:52:53 2002
@@ -3035,7 +3035,15 @@
 	jfs_ip->mode2 = le32_to_cpu(dip->di_mode);
 
 	ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
-	ip->i_nlink = le32_to_cpu(dip->di_nlink);
+
+	jfs_ip->nlink_real = le32_to_cpu(dip->di_nlink);
+	if (jfs_ip->nlink_real <= VFS_LINK_MAX)
+		ip->i_nlink = jfs_ip->nlink_real;
+	else if (S_ISDIR(ip->i_mode))
+		ip->i_nlink = 1;
+	else
+		ip->i_nlink = VFS_LINK_MAX;
+
 	ip->i_uid = le32_to_cpu(dip->di_uid);
 	ip->i_gid = le32_to_cpu(dip->di_gid);
 	ip->i_size = le64_to_cpu(dip->di_size);
@@ -3089,7 +3097,7 @@
 	dip->di_gen = cpu_to_le32(ip->i_generation);
 	dip->di_size = cpu_to_le64(ip->i_size);
 	dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
-	dip->di_nlink = cpu_to_le32(ip->i_nlink);
+	dip->di_nlink = cpu_to_le32(jfs_ip->nlink_real);
 	dip->di_uid = cpu_to_le32(ip->i_uid);
 	dip->di_gid = cpu_to_le32(ip->i_gid);
 	/*
===== fs/jfs/jfs_incore.h 1.5 vs edited =====
--- 1.5/fs/jfs/jfs_incore.h	Mon Sep  2 05:48:42 2002
+++ edited/fs/jfs/jfs_incore.h	Thu Sep  5 10:12:09 2002
@@ -38,6 +38,7 @@
 	struct inode *inode;	/* pointer back to fs-independent inode */
 	int	fileset;	/* fileset number (always 16)*/
 	uint	mode2;		/* jfs-specific mode		*/
+	uint	nlink_real;	/* i_nlink is too short		*/
 	pxd_t   ixpxd;		/* inode extent descriptor	*/
 	dxd_t	acl;		/* dxd describing acl	*/
 	dxd_t	ea;		/* dxd describing ea	*/
===== fs/jfs/namei.c 1.9 vs edited =====
--- 1.9/fs/jfs/namei.c	Mon Aug 26 14:07:42 2002
+++ edited/fs/jfs/namei.c	Thu Sep  5 11:11:57 2002
@@ -44,6 +44,34 @@
 s64 commitZeroLink(tid_t, struct inode *);
 
 /*
+ * i_nlink accounting
+ * Keep track of real link count, while keeping i_nlink, which may be too
+ * small to hold the real value, sane.
+ */
+static inline void INC_INODE_NLINK(struct inode *inode)
+{
+	if (++JFS_IP(inode)->nlink_real <= VFS_LINK_MAX)
+		inode->i_nlink = JFS_IP(inode)->nlink_real;
+}
+static inline void DEC_INODE_NLINK(struct inode *inode)
+{
+	if (--JFS_IP(inode)->nlink_real <= VFS_LINK_MAX)
+		inode->i_nlink = JFS_IP(inode)->nlink_real;
+}
+/*
+ * Due to an optimazation in the find command (and other cases?),
+ * set i_nlink to one if i_nlink can't be correct.
+ */
+static inline void INC_DIR_INODE_NLINK(struct inode *inode)
+{
+	if (++JFS_IP(inode)->nlink_real <= VFS_LINK_MAX)
+		inode->i_nlink = JFS_IP(inode)->nlink_real;
+	else
+		inode->i_nlink = 1;
+}
+#define DEC_DIR_INODE_NLINK DEC_INODE_NLINK
+
+/*
  * NAME:	jfs_create(dip, dentry, mode)
  *
  * FUNCTION:	create a regular file in the parent directory <dip>
@@ -142,7 +170,7 @@
 	up(&JFS_IP(dip)->commit_sem);
 	up(&JFS_IP(ip)->commit_sem);
 	if (rc) {
-		ip->i_nlink = 0;
+		ip->i_nlink = JFS_IP(ip)->nlink_real = 0;
 		iput(ip);
 	}
 
@@ -185,7 +213,7 @@
 	jFYI(1, ("jfs_mkdir: dip:0x%p name:%s\n", dip, dentry->d_name.name));
 
 	/* link count overflow on parent directory ? */
-	if (dip->i_nlink == JFS_LINK_MAX) {
+	if (JFS_IP(dip)->nlink_real == JFS_LINK_MAX) {
 		rc = EMLINK;
 		goto out1;
 	}
@@ -245,7 +273,7 @@
 		goto out3;
 	}
 
-	ip->i_nlink = 2;	/* for '.' */
+	ip->i_nlink = JFS_IP(ip)->nlink_real = 2;	/* for '.' */
 	ip->i_op = &jfs_dir_inode_operations;
 	ip->i_fop = &jfs_dir_operations;
 	ip->i_mapping->a_ops = &jfs_aops;
@@ -256,7 +284,7 @@
 	d_instantiate(dentry, ip);
 
 	/* update parent directory inode */
-	dip->i_nlink++;		/* for '..' from child directory */
+	INC_DIR_INODE_NLINK(dip);	/* for '..' from child directory */
 	dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dip);
 
@@ -267,7 +295,7 @@
 	up(&JFS_IP(dip)->commit_sem);
 	up(&JFS_IP(ip)->commit_sem);
 	if (rc) {
-		ip->i_nlink = 0;
+		ip->i_nlink = JFS_IP(ip)->nlink_real = 0;
 		iput(ip);
 	}
 
@@ -351,7 +379,7 @@
 	/* update parent directory's link count corresponding
 	 * to ".." entry of the target directory deleted
 	 */
-	dip->i_nlink--;
+	DEC_DIR_INODE_NLINK(dip);
 	dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dip);
 
@@ -373,7 +401,7 @@
 	JFS_IP(ip)->acl.flag = 0;
 
 	/* mark the target directory as deleted */
-	ip->i_nlink = 0;
+	ip->i_nlink = JFS_IP(ip)->nlink_real = 0;
 	mark_inode_dirty(ip);
 
 	rc = txCommit(tid, 2, &iplist[0], 0);
@@ -470,7 +498,7 @@
 	mark_inode_dirty(dip);
 
 	/* update target's inode */
-	ip->i_nlink--;
+	DEC_INODE_NLINK(ip);
 	mark_inode_dirty(ip);
 
 	/*
@@ -768,7 +796,7 @@
 	down(&JFS_IP(dir)->commit_sem);
 	down(&JFS_IP(ip)->commit_sem);
 
-	if (ip->i_nlink == JFS_LINK_MAX) {
+	if (JFS_IP(ip)->nlink_real == JFS_LINK_MAX) {
 		rc = EMLINK;
 		goto out;
 	}
@@ -790,7 +818,7 @@
 		goto out;
 
 	/* update object inode */
-	ip->i_nlink++;		/* for new link */
+	INC_INODE_NLINK(ip);
 	ip->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(dir);
 	atomic_inc(&ip->i_count);
@@ -1004,7 +1032,7 @@
 	up(&JFS_IP(dip)->commit_sem);
 	up(&JFS_IP(ip)->commit_sem);
 	if (rc) {
-		ip->i_nlink = 0;
+		ip->i_nlink = JFS_IP(ip)->nlink_real = 0;
 		iput(ip);
 	}
 
@@ -1091,7 +1119,7 @@
 				goto out3;
 			}
 		} else if ((new_dir != old_dir) &&
-			   (new_dir->i_nlink == JFS_LINK_MAX)) {
+			   (JFS_IP(new_dir)->nlink_real == JFS_LINK_MAX)) {
 			rc = EMLINK;
 			goto out3;
 		}
@@ -1118,9 +1146,9 @@
 			      old_ip->i_ino, JFS_RENAME);
 		if (rc)
 			goto out4;
-		new_ip->i_nlink--;
+		DEC_INODE_NLINK(new_ip);
 		if (S_ISDIR(new_ip->i_mode)) {
-			new_ip->i_nlink--;
+			DEC_DIR_INODE_NLINK(new_ip);
 			assert(new_ip->i_nlink == 0);
 			tblk = tid_to_tblock(tid);
 			tblk->xflag |= COMMIT_DELETE;
@@ -1162,7 +1190,7 @@
 			goto out4;
 		}
 		if (S_ISDIR(old_ip->i_mode))
-			new_dir->i_nlink++;
+			INC_DIR_INODE_NLINK(new_dir);
 	}
 	/*
 	 * Remove old directory entry
@@ -1178,7 +1206,7 @@
 		goto out4;
 	}
 	if (S_ISDIR(old_ip->i_mode)) {
-		old_dir->i_nlink--;
+		DEC_DIR_INODE_NLINK(old_dir);
 		if (old_dir != new_dir) {
 			/*
 			 * Change inode number of parent for moved directory
@@ -1351,7 +1379,7 @@
 	up(&JFS_IP(ip)->commit_sem);
 	up(&JFS_IP(dir)->commit_sem);
 	if (rc) {
-		ip->i_nlink = 0;
+		ip->i_nlink = JFS_IP(ip)->nlink_real = 0;
 		iput(ip);
 	}
 



  reply	other threads:[~2002-09-05 17:53 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-01  8:55 [PATCH] sparc32: wrong type of nlink_t Tomas Szepe
2002-09-01  8:52 ` David S. Miller
2002-09-01  9:44   ` Tomas Szepe
2002-09-04 20:18     ` Dave Kleikamp
2002-09-04 20:29       ` [reiserfs-dev] " Chris Mason
2002-09-04 23:34         ` David S. Miller
2002-09-06  8:52         ` David Woodhouse
2002-09-04 20:31       ` Hans Reiser
2002-09-04 21:18         ` Tomas Szepe
2002-09-04 21:44           ` Thunder from the hill
2002-09-04 21:57             ` Thunder from the hill
2002-09-04 23:35         ` David S. Miller
2002-09-05  0:36           ` Hans Reiser
2002-09-05  0:32             ` David S. Miller
2002-09-05  0:49             ` Chris Mason
2002-09-05  5:40               ` Tomas Szepe
2002-09-05  5:36                 ` David S. Miller
2002-09-05  5:48                   ` Tomas Szepe
2002-09-05  5:45                     ` David S. Miller
2002-09-05  9:46                       ` Nikita Danilov
2002-09-05  5:56                     ` Oleg Drokin
2002-09-05  5:52                       ` David S. Miller
2002-09-05  6:07                         ` Oleg Drokin
2002-09-05  5:59                       ` Tomas Szepe
2002-09-05  9:54                   ` Oleg Drokin
2002-09-05 10:50                     ` David S. Miller
2002-09-05 13:49                     ` Oleg Drokin
2002-09-05 13:57                       ` Oleg Drokin
2002-09-05 14:03                       ` Chris Mason
2002-09-05 14:17                         ` Oleg Drokin
2002-09-05 16:45                           ` Chris Mason
2002-09-05 17:25                             ` Oleg Drokin
2002-09-05 21:18                               ` jw schultz
2002-09-05 22:02                                 ` Ragnar Kjørstad
2002-09-05 22:57                                   ` jw schultz
2002-09-06  0:01                                     ` Ragnar Kjørstad
2002-09-06  1:41                                       ` jw schultz
2002-09-06  2:29                                         ` Ragnar Kjørstad
2002-09-05 16:09                     ` Dave Kleikamp
2002-09-05 16:13                       ` Oleg Drokin
2002-09-05 17:58                         ` Dave Kleikamp [this message]
2002-09-06 13:54                           ` Oleg Drokin
2002-09-05 17:24                     ` Linus Torvalds
2002-09-04 23:33       ` David S. Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200209051258.27366.shaggy@austin.ibm.com \
    --to=shaggy@austin.ibm.com \
    --cc=davem@redhat.com \
    --cc=green@namesys.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxjfs@us.ibm.com \
    --cc=mason@suse.com \
    --cc=reiserfs-dev@namesys.com \
    --cc=szepe@pinerecords.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).