kern/181012: [patch] Implemented linux system call fstatfs64

Yuri yuri at tsoft.com
Sun Aug 4 10:50:01 UTC 2013


>Number:         181012
>Category:       kern
>Synopsis:       [patch] Implemented linux system call fstatfs64
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 04 10:50:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Yuri
>Release:        9.1
>Organization:
n/a
>Environment:
>Description:
This patch implements linux call fstatfs64.
Patch also fixes the problem when linux call fstatfs would return wrong values when actual FS stat value(s) are large enough to not fit into 32 bits.
Patch is against rev.251126

Please also merge it into 9.X stable branch.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

--- sys/compat/linux/linux_stats.c	(revision 251126)
+++ sys/compat/linux/linux_stats.c	(working copy)
@@ -377,20 +377,27 @@
 	return (0L);
 }
 
-static void
+static int
 bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
 {
-
 	linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
 	linux_statfs->f_bsize = bsd_statfs->f_bsize;
 	linux_statfs->f_blocks = bsd_statfs->f_blocks;
 	linux_statfs->f_bfree = bsd_statfs->f_bfree;
 	linux_statfs->f_bavail = bsd_statfs->f_bavail;
+	linux_statfs->f_files = bsd_statfs->f_files;
 	linux_statfs->f_ffree = bsd_statfs->f_ffree;
-	linux_statfs->f_files = bsd_statfs->f_files;
 	linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
 	linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
 	linux_statfs->f_namelen = MAXNAMLEN;
+
+	if ((uint64_t)linux_statfs->f_blocks != bsd_statfs->f_blocks ||
+	    (uint64_t)linux_statfs->f_bfree != bsd_statfs->f_bfree ||
+	    (int64_t)linux_statfs->f_bavail != bsd_statfs->f_bavail ||
+	    (uint64_t)linux_statfs->f_files != bsd_statfs->f_files ||
+	    (int64_t)linux_statfs->f_ffree != bsd_statfs->f_ffree)
+		return EOVERFLOW;
+	return 0;
 }
 
 int
@@ -415,23 +422,44 @@
 	LFREEPATH(path);
 	if (error)
 		return (error);
-	bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+	error = bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+	if (error)
+		return (error);
 	if (dev_shm)
 		linux_statfs.f_type = LINUX_SHMFS_MAGIC;
 	return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
 }
 
+int
+linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
+{
+	struct l_statfs linux_statfs;
+	struct statfs bsd_statfs;
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(fstatfs))
+		printf(ARGS(fstatfs, "%d, *"), args->fd);
+#endif
+	error = kern_fstatfs(td, args->fd, &bsd_statfs);
+	if (error)
+		return error;
+	bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+	if (error)
+		return (error);
+	return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+}
+
 static void
 bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
 {
-
 	linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
 	linux_statfs->f_bsize = bsd_statfs->f_bsize;
 	linux_statfs->f_blocks = bsd_statfs->f_blocks;
 	linux_statfs->f_bfree = bsd_statfs->f_bfree;
 	linux_statfs->f_bavail = bsd_statfs->f_bavail;
+	linux_statfs->f_files = bsd_statfs->f_files;
 	linux_statfs->f_ffree = bsd_statfs->f_ffree;
-	linux_statfs->f_files = bsd_statfs->f_files;
 	linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
 	linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
 	linux_statfs->f_namelen = MAXNAMLEN;
@@ -463,9 +491,9 @@
 }
 
 int
-linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
+linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
 {
-	struct l_statfs linux_statfs;
+	struct l_statfs64 linux_statfs;
 	struct statfs bsd_statfs;
 	int error;
 
@@ -476,7 +504,7 @@
 	error = kern_fstatfs(td, args->fd, &bsd_statfs);
 	if (error)
 		return error;
-	bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+	bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
 	return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
 }
 
--- sys/amd64/linux32/linux32_proto.h	(revision 251126)
+++ sys/amd64/linux32/linux32_proto.h	(working copy)
@@ -820,7 +820,8 @@
 	char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
 };
 struct linux_fstatfs64_args {
-	register_t dummy;
+	char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)];
+	char buf_l_[PADL_(struct l_statfs_buf *)]; struct l_statfs_buf * buf; char buf_r_[PADR_(struct l_statfs_buf *)];
 };
 struct linux_tgkill_args {
 	char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)];
--- sys/i386/linux/linux_proto.h	(revision 251126)
+++ sys/i386/linux/linux_proto.h	(working copy)
@@ -825,7 +825,8 @@
 	char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
 };
 struct linux_fstatfs64_args {
-	register_t dummy;
+	char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)];
+	char buf_l_[PADL_(struct l_statfs_buf *)]; struct l_statfs_buf * buf; char buf_r_[PADR_(struct l_statfs_buf *)];
 };
 struct linux_tgkill_args {
 	char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)];
--- sys/amd64/linux32/linux32_dummy.c	(revision 251126)
+++ sys/amd64/linux32/linux32_dummy.c	(working copy)
@@ -79,7 +79,6 @@
 DUMMY(timer_gettime);
 DUMMY(timer_getoverrun);
 DUMMY(timer_delete);
-DUMMY(fstatfs64);
 DUMMY(mbind);
 DUMMY(get_mempolicy);
 DUMMY(set_mempolicy);
--- sys/i386/linux/linux_dummy.c	(revision 251126)
+++ sys/i386/linux/linux_dummy.c	(working copy)
@@ -76,7 +76,6 @@
 DUMMY(epoll_ctl);
 DUMMY(epoll_wait);
 DUMMY(remap_file_pages);
-DUMMY(fstatfs64);
 DUMMY(mbind);
 DUMMY(get_mempolicy);
 DUMMY(set_mempolicy);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list