Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Nov 2014 17:50:22 -0800
From:      Gleb Kurtsou <gleb@freebsd.org>
To:        Rick Macklem <rmacklem@uoguelph.ca>
Cc:        freebsd-fs@freebsd.org
Subject:   Re: RFC: patch to make d_fileno 64bits
Message-ID:  <20141123015021.GA1658@reks>
In-Reply-To: <1346064334.5234809.1416616386575.JavaMail.root@uoguelph.ca>
References:  <20141121182219.GA1076@reks> <1346064334.5234809.1416616386575.JavaMail.root@uoguelph.ca>

next in thread | previous in thread | raw e-mail | index | archive | help

--SUOF0GtieIMvvwua
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline

On (21/11/2014 19:33), Rick Macklem wrote:
> Gleb Kurtsou wrote:
> > On (21/11/2014 10:25), John Baldwin wrote:
[...]
> > > 
> > > I think this is already done (along with several other changes)
> > > more fully in
> > > the projects/ino64 branch in svn?
> > 
> > projects/ino64 was created by mdf for merging GSoC commits, and it
> > didn't even get half way through.
> > 
> > I'm currently working on merging the code to CURRENT. It's been more
> > than 2 years, so there is quite some work in there. I intend to
> > update
> > the branch as soon as code is ready for review.
> > 
> Btw, I just took a quick look and I didn't find any changes to "struct dirent"
> in projects/ino64, so I think my original assumption that this piece of the
> puzzle hadn't yet been solved, is correct. (Gleb, if you had changes to
> "struct dirent" and related fs changes, please let me know.)

projects/ino64 was created for merging GSoC commits. The branch is
incomplete to say the least.. There are preparatory changes in there
only. In case you are interested please refer to
https://github.com/glk/freebsd-ino64/commits/projects/ino64

BTW original GSoC branch also changes VOP_READDIR for all file systems
to populate dirent.d_off.

I've attached the patch for some of the system headers generated by
git diff -r 531f5069a9b0f61b8ecd08e4ed744cec3b022606 -r github/projects/ino64 sys/sys/{_types,dirent,mount,stat}.h > ~/ino64-sys-sys.patch

> 
> Oh, and thanks to some comments, the new struct dirent has already changed to:
> 
> struct dirent {
>    __uint64_t  d_cookie; /* dir cookie for next dir entry */
>    __uint64_t  d_fileno;
>    __uint16_t  d_reclen;
>    __uint8_t   d_type;
>    __uint8_t   d_namlen;
>    __uint8_t   d_pad[4]; /* align d_name to 8 byte boundary */
>    __uint8_t   d_name[MAXNAMLEN + 1];
> };

GSoC'2011 code:
struct dirent {
	ino_t      d_fileno;		/* file number of entry */
	off_t      d_off;		/* next entry seek offset */
	__uint16_t d_reclen;		/* length of this record */
	__uint16_t d_namlen;		/* length of string in d_name */
	__uint8_t  d_type; 		/* file type, see below */
	__uint8_t  d_unused1;
	__uint16_t d_unused2;
	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
};

> 
> It was pointed out that C would pad the structure to a multiple of 8 bytes
> for some arches and without d_pad that would imply d_name wasn't at the end
> of the structure. (Apparently code somewhere find d_name by subtracting MAXNAMLEN + 1
> from sizeof(struct dirent) and this fails if d_name isn't at the end. Yuck,
> but the above fixes it.)
> 
> However, the size of d_namlen could become uint16_t, if anyone thinks MAXNAMLEN
> might want to be greater than 255 someday (long away, since that's another ABI change).

Somebody has already mentioned it previously so I've bumped it to uint16
back than.


> 
> rick
> 
> > Besides branch also changes dev_t to 64-bit, bumps MNAMELEN to 1024
> > and
> > has complete ABI compatibility shims (probably except openaudit which
> > had
> > issues).
> > 
> > 
> > _______________________________________________
> > freebsd-fs@freebsd.org mailing list
> > http://lists.freebsd.org/mailman/listinfo/freebsd-fs
> > To unsubscribe, send any mail to "freebsd-fs-unsubscribe@freebsd.org"
> > 

--SUOF0GtieIMvvwua
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment; filename="ino64-sys-sys.patch"

diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index c59afd3..2d757f5 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -32,37 +32,37 @@
 #include <sys/cdefs.h>
 #include <machine/_types.h>
 
 /*
  * Standard type definitions.
  */
 typedef	__uint32_t	__blksize_t;	/* file block size */
 typedef	__int64_t	__blkcnt_t;	/* file block count */
 typedef	__int32_t	__clockid_t;	/* clock_gettime()... */
 typedef	__uint64_t	__cap_rights_t;	/* capability rights */
 typedef	__uint32_t	__fflags_t;	/* file flags */
 typedef	__uint64_t	__fsblkcnt_t;
 typedef	__uint64_t	__fsfilcnt_t;
 typedef	__uint32_t	__gid_t;
 typedef	__int64_t	__id_t;		/* can hold a gid_t, pid_t, or uid_t */
-typedef	__uint32_t	__ino_t;	/* inode number */
+typedef	__uint64_t	__ino_t;	/* inode number */
 typedef	long		__key_t;	/* IPC key (for Sys V IPC) */
 typedef	__int32_t	__lwpid_t;	/* Thread ID (a.k.a. LWP) */
 typedef	__uint16_t	__mode_t;	/* permissions */
 typedef	int		__accmode_t;	/* access permissions */
 typedef	int		__nl_item;
-typedef	__uint16_t	__nlink_t;	/* link count */
+typedef	__uint32_t	__nlink_t;	/* link count */
 typedef	__int64_t	__off_t;	/* file offset */
 typedef	__int32_t	__pid_t;	/* process [group] */
 typedef	__int64_t	__rlim_t;	/* resource limit - intentionally */
 					/* signed, because of legacy code */
 					/* that uses -1 for RLIM_INFINITY */
 typedef	__uint8_t	__sa_family_t;
 typedef	__uint32_t	__socklen_t;
 typedef	long		__suseconds_t;	/* microseconds (signed) */
 typedef	struct __timer	*__timer_t;	/* timer_gettime()... */
 typedef	struct __mq	*__mqd_t;	/* mq_open()... */
 typedef	__uint32_t	__uid_t;
 typedef	unsigned int	__useconds_t;	/* microseconds (unsigned) */
 typedef	int		__cpuwhich_t;	/* which parameter for cpuset. */
 typedef	int		__cpulevel_t;	/* level parameter for cpuset. */
 typedef int		__cpusetid_t;	/* cpuset identifier. */
@@ -78,29 +78,29 @@ typedef int		__cpusetid_t;	/* cpuset identifier. */
  * ints cannot hold 32 bits, you will be in trouble.  The reason an int was
  * chosen over a long is that the is*() and to*() routines take ints (says
  * ANSI C), but they use __ct_rune_t instead of int.
  *
  * NOTE: rune_t is not covered by ANSI nor other standards, and should not
  * be instantiated outside of lib/libc/locale.  Use wchar_t.  wchar_t and
  * rune_t must be the same type.  Also, wint_t must be no narrower than
  * wchar_t, and should be able to hold all members of the largest
  * character set plus one extra value (WEOF), and must be at least 16 bits.
  */
 typedef	int		__ct_rune_t;	/* arg type for ctype funcs */
 typedef	__ct_rune_t	__rune_t;	/* rune_t (see above) */
 typedef	__ct_rune_t	__wchar_t;	/* wchar_t (see above) */
 typedef	__ct_rune_t	__wint_t;	/* wint_t (see above) */
 
-typedef	__uint32_t	__dev_t;	/* device number */
+typedef	__uint64_t	__dev_t;	/* device number */
 
 typedef	__uint32_t	__fixpt_t;	/* fixed point number */
 
 /*
  * mbstate_t is an opaque object to keep conversion state during multibyte
  * stream conversions.
  */
 typedef union {
 	char		__mbstate8[128];
 	__int64_t	_mbstateL;	/* for alignment */
 } __mbstate_t;
 
 #endif /* !_SYS__TYPES_H_ */
diff --git a/sys/sys/dirent.h b/sys/sys/dirent.h
index dfaacff..107936b 100644
--- a/sys/sys/dirent.h
+++ b/sys/sys/dirent.h
@@ -24,55 +24,76 @@
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  *	@(#)dirent.h	8.3 (Berkeley) 8/10/94
  * $FreeBSD$
  */
 
 #ifndef	_SYS_DIRENT_H_
 #define	_SYS_DIRENT_H_
 
 #include <sys/cdefs.h>
 #include <sys/_types.h>
 
+#ifndef _INO_T_DECLARED
+typedef	__ino_t		ino_t;
+#define	_INO_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef	__off_t		off_t;
+#define	_OFF_T_DECLARED
+#endif
+
 /*
  * The dirent structure defines the format of directory entries returned by
  * the getdirentries(2) system call.
  *
  * A directory entry has a struct dirent at the front of it, containing its
  * inode number, the length of the entry, and the length of the name
  * contained in the entry.  These are followed by the name padded to a 4
  * byte boundary with null bytes.  All names are guaranteed null terminated.
  * The maximum length of a name in a directory is MAXNAMLEN.
  */
 
 struct dirent {
-	__uint32_t d_fileno;		/* file number of entry */
+	ino_t      d_fileno;		/* file number of entry */
+	off_t      d_off;		/* next entry seek offset */
 	__uint16_t d_reclen;		/* length of this record */
+	__uint16_t d_namlen;		/* length of string in d_name */
 	__uint8_t  d_type; 		/* file type, see below */
-	__uint8_t  d_namlen;		/* length of string in d_name */
+	__uint8_t  d_unused1;
+	__uint16_t d_unused2;
 #if __BSD_VISIBLE
 #define	MAXNAMLEN	255
 	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
 #else
 	char	d_name[255 + 1];	/* name must be no longer than this */
 #endif
 };
 
 #if __BSD_VISIBLE
+struct freebsd9_dirent {
+	__uint32_t d_fileno;		/* file number of entry */
+	__uint16_t d_reclen;		/* length of this record */
+	__uint8_t  d_type; 		/* file type, see below */
+	__uint8_t  d_namlen;		/* length of string in d_name */
+	char	d_name[255 + 1];	/* name must be no longer than this */
+};
+
 /*
  * File types
  */
 #define	DT_UNKNOWN	 0
 #define	DT_FIFO		 1
 #define	DT_CHR		 2
 #define	DT_DIR		 4
 #define	DT_BLK		 6
 #define	DT_REG		 8
 #define	DT_LNK		10
 #define	DT_SOCK		12
 #define	DT_WHT		14
 
 /*
  * Convert between stat structure types and directory types.
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index ecaf7b8..01f9e04 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -52,57 +52,83 @@ typedef struct fsid { int32_t val[2]; } fsid_t;	/* filesystem id type */
  * File identifier.
  * These are unique per filesystem on a single machine.
  */
 #define	MAXFIDSZ	16
 
 struct fid {
 	u_short		fid_len;		/* length of data in bytes */
 	u_short		fid_data0;		/* force longword alignment */
 	char		fid_data[MAXFIDSZ];	/* data (variable length) */
 };
 
 /*
  * filesystem statistics
  */
 #define	MFSNAMELEN	16		/* length of type name including null */
-#define	MNAMELEN	88		/* size of on/from name bufs */
-#define	STATFS_VERSION	0x20030518	/* current version number */
+#define	MNAMELEN	1024		/* size of on/from name bufs */
+#define	STATFS_VERSION	0x20110618	/* current version number */
 struct statfs {
 	uint32_t f_version;		/* structure version number */
 	uint32_t f_type;		/* type of filesystem */
 	uint64_t f_flags;		/* copy of mount exported flags */
 	uint64_t f_bsize;		/* filesystem fragment size */
 	uint64_t f_iosize;		/* optimal transfer block size */
 	uint64_t f_blocks;		/* total data blocks in filesystem */
 	uint64_t f_bfree;		/* free blocks in filesystem */
 	int64_t	 f_bavail;		/* free blocks avail to non-superuser */
 	uint64_t f_files;		/* total file nodes in filesystem */
 	int64_t	 f_ffree;		/* free nodes avail to non-superuser */
 	uint64_t f_syncwrites;		/* count of sync writes since mount */
 	uint64_t f_asyncwrites;		/* count of async writes since mount */
 	uint64_t f_syncreads;		/* count of sync reads since mount */
 	uint64_t f_asyncreads;		/* count of async reads since mount */
 	uint64_t f_spare[10];		/* unused spare */
 	uint32_t f_namemax;		/* maximum filename length */
 	uid_t	  f_owner;		/* user that mounted the filesystem */
 	fsid_t	  f_fsid;		/* filesystem id */
 	char	  f_charspare[80];	    /* spare string space */
 	char	  f_fstypename[MFSNAMELEN]; /* filesystem type name */
 	char	  f_mntfromname[MNAMELEN];  /* mounted filesystem */
 	char	  f_mntonname[MNAMELEN];    /* directory on which mounted */
 };
 
+#define	FREEBSD9_STATFS_VERSION	0x20030518	/* current version number */
+struct freebsd9_statfs {
+	uint32_t f_version;		/* structure version number */
+	uint32_t f_type;		/* type of filesystem */
+	uint64_t f_flags;		/* copy of mount exported flags */
+	uint64_t f_bsize;		/* filesystem fragment size */
+	uint64_t f_iosize;		/* optimal transfer block size */
+	uint64_t f_blocks;		/* total data blocks in filesystem */
+	uint64_t f_bfree;		/* free blocks in filesystem */
+	int64_t	 f_bavail;		/* free blocks avail to non-superuser */
+	uint64_t f_files;		/* total file nodes in filesystem */
+	int64_t	 f_ffree;		/* free nodes avail to non-superuser */
+	uint64_t f_syncwrites;		/* count of sync writes since mount */
+	uint64_t f_asyncwrites;		/* count of async writes since mount */
+	uint64_t f_syncreads;		/* count of sync reads since mount */
+	uint64_t f_asyncreads;		/* count of async reads since mount */
+	uint64_t f_spare[10];		/* unused spare */
+	uint32_t f_namemax;		/* maximum filename length */
+	uid_t	  f_owner;		/* user that mounted the filesystem */
+	fsid_t	  f_fsid;		/* filesystem id */
+	char	  f_charspare[80];	/* spare string space */
+	char	  f_fstypename[16];	/* filesystem type name */
+	char	  f_mntfromname[88];	/* mounted filesystem */
+	char	  f_mntonname[88];	/* directory on which mounted */
+};
+
 #ifdef _KERNEL
 #define	OMFSNAMELEN	16	/* length of fs type name, including null */
 #define	OMNAMELEN	(88 - 2 * sizeof(long))	/* size of on/from name bufs */
 
 /* XXX getfsstat.2 is out of date with write and read counter changes here. */
 /* XXX statfs.2 is out of date with read counter changes here. */
 struct ostatfs {
 	long	f_spare2;		/* placeholder */
 	long	f_bsize;		/* fundamental filesystem block size */
 	long	f_iosize;		/* optimal transfer block size */
 	long	f_blocks;		/* total data blocks in filesystem */
 	long	f_bfree;		/* free blocks in fs */
 	long	f_bavail;		/* free blocks avail to non-superuser */
 	long	f_files;		/* total file nodes in filesystem */
 	long	f_ffree;		/* free file nodes in fs */
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index 1b03bd2..a9b5ff4 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -90,86 +90,117 @@ typedef	__off_t		off_t;
 #ifndef _UID_T_DECLARED
 typedef	__uid_t		uid_t;
 #define	_UID_T_DECLARED
 #endif
 
 #if !defined(_KERNEL) && __BSD_VISIBLE
 /*
  * XXX We get miscellaneous namespace pollution with this.
  */
 #include <sys/time.h>
 #endif
 
 #if __BSD_VISIBLE
 struct ostat {
 	__uint16_t st_dev;		/* inode's device */
-	ino_t	  st_ino;		/* inode's number */
+	__uint32_t st_ino;		/* inode's number */
 	mode_t	  st_mode;		/* inode protection mode */
-	nlink_t	  st_nlink;		/* number of hard links */
+	__uint16_t st_nlink;		/* number of hard links */
 	__uint16_t st_uid;		/* user ID of the file's owner */
 	__uint16_t st_gid;		/* group ID of the file's group */
 	__uint16_t st_rdev;		/* device type */
 	__int32_t st_size;		/* file size, in bytes */
 	struct	timespec st_atim;	/* time of last access */
 	struct	timespec st_mtim;	/* time of last data modification */
 	struct	timespec st_ctim;	/* time of last file status change */
 	__int32_t st_blksize;		/* optimal blocksize for I/O */
 	__int32_t st_blocks;		/* blocks allocated for file */
 	fflags_t  st_flags;		/* user defined flags for file */
 	__uint32_t st_gen;		/* file generation number */
 };
+
+struct freebsd9_stat {
+	__uint32_t st_dev;		/* inode's device */
+	__uint32_t st_ino;		/* inode's number */
+	mode_t	  st_mode;		/* inode protection mode */
+	__uint16_t st_nlink;		/* number of hard links */
+	uid_t	  st_uid;		/* user ID of the file's owner */
+	gid_t	  st_gid;		/* group ID of the file's group */
+	__uint32_t st_rdev;		/* device type */
+	struct	timespec st_atim;	/* time of last access */
+	struct	timespec st_mtim;	/* time of last data modification */
+	struct	timespec st_ctim;	/* time of last file status change */
+	off_t	  st_size;		/* file size, in bytes */
+	blkcnt_t st_blocks;		/* blocks allocated for file */
+	blksize_t st_blksize;		/* optimal blocksize for I/O */
+	fflags_t  st_flags;		/* user defined flags for file */
+	__uint32_t st_gen;		/* file generation number */
+	__int32_t st_lspare;
+	struct timespec st_birthtim;	/* time of file creation */
+	/*
+	 * Explicitly pad st_birthtim to 16 bytes so that the size of
+	 * struct stat is backwards compatible.  We use bitfields instead
+	 * of an array of chars so that this doesn't require a C99 compiler
+	 * to compile if the size of the padding is 0.  We use 2 bitfields
+	 * to cover up to 64 bits on 32-bit machines.  We assume that
+	 * CHAR_BIT is 8...
+	 */
+	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
+	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
+};
 #endif /* __BSD_VISIBLE */
 
 struct stat {
-	__dev_t   st_dev;		/* inode's device */
+	dev_t     st_dev;		/* inode's device */
 	ino_t	  st_ino;		/* inode's number */
-	mode_t	  st_mode;		/* inode protection mode */
 	nlink_t	  st_nlink;		/* number of hard links */
+	mode_t	  st_mode;		/* inode protection mode */
+	__int16_t st_padding0;
 	uid_t	  st_uid;		/* user ID of the file's owner */
 	gid_t	  st_gid;		/* group ID of the file's group */
-	__dev_t   st_rdev;		/* device type */
+	dev_t     st_rdev;		/* device type */
 	struct	timespec st_atim;	/* time of last access */
 	struct	timespec st_mtim;	/* time of last data modification */
 	struct	timespec st_ctim;	/* time of last file status change */
 	off_t	  st_size;		/* file size, in bytes */
 	blkcnt_t st_blocks;		/* blocks allocated for file */
 	blksize_t st_blksize;		/* optimal blocksize for I/O */
 	fflags_t  st_flags;		/* user defined flags for file */
 	__uint32_t st_gen;		/* file generation number */
 	__int32_t st_lspare;
 	struct timespec st_birthtim;	/* time of file creation */
 	/*
 	 * Explicitly pad st_birthtim to 16 bytes so that the size of
 	 * struct stat is backwards compatible.  We use bitfields instead
 	 * of an array of chars so that this doesn't require a C99 compiler
 	 * to compile if the size of the padding is 0.  We use 2 bitfields
 	 * to cover up to 64 bits on 32-bit machines.  We assume that
 	 * CHAR_BIT is 8...
 	 */
 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
 };
 
 #if __BSD_VISIBLE
 struct nstat {
-	__dev_t   st_dev;		/* inode's device */
-	ino_t	  st_ino;		/* inode's number */
+	__uint32_t st_dev;		/* inode's device */
+	__uint32_t st_ino;		/* inode's number */
 	__uint32_t st_mode;		/* inode protection mode */
 	__uint32_t st_nlink;		/* number of hard links */
 	uid_t	  st_uid;		/* user ID of the file's owner */
 	gid_t	  st_gid;		/* group ID of the file's group */
-	__dev_t   st_rdev;		/* device type */
+	__uint32_t st_rdev;		/* device type */
 	struct	timespec st_atim;	/* time of last access */
 	struct	timespec st_mtim;	/* time of last data modification */
 	struct	timespec st_ctim;	/* time of last file status change */
 	off_t	  st_size;		/* file size, in bytes */
 	blkcnt_t st_blocks;		/* blocks allocated for file */
 	blksize_t st_blksize;		/* optimal blocksize for I/O */
 	fflags_t  st_flags;		/* user defined flags for file */
 	__uint32_t st_gen;		/* file generation number */
 	struct timespec st_birthtim;	/* time of file creation */
 	/*
 	 * See above about the following padding.
 	 */
 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
 };

--SUOF0GtieIMvvwua--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20141123015021.GA1658>