This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch, master, updated. glibc-2.14-92-g4e5f31c


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  4e5f31c847982997c856f03bbc35134e9fd0f61f (commit)
      from  de283087c74f720cf8a7171972e72b5fa2b45e79 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4e5f31c847982997c856f03bbc35134e9fd0f61f

commit 4e5f31c847982997c856f03bbc35134e9fd0f61f
Author: Ulrich Drepper <drepper@gmail.com>
Date:   Thu Jul 7 10:53:16 2011 -0400

    Handle ext4 in {,f}pathconf
    
    ext4 has a higher LINK_MAX limit than ext2/3.  Unfortunately it is
    not easy to distinguish the filesystems from userlevel.

diff --git a/ChangeLog b/ChangeLog
index 6225871..050bff3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2011-07-07  Ulrich Drepper  <drepper@gmail.com>
 
+	* sysdeps/unix/sysv/linux/pathconf.c (distinguish_extX): New function.
+	(__statfs_link_max): Use it to dostinguish between ext2/3 and ext4.
+	The latter has a higher limit.  Take additional parameter to pass to
+	the new function.
+	(__pathconf): Pass file to __statfs_link_max.
+	* sysdeps/unix/sysv/linux/fpathconf.c (__fpathconf): Pass fd to
+	__statfs_link_max.
+	* sysdeps/unix/sysv/linux/pathconf.h: Adjust prototype of
+	__statfs_link_max.
+
 	[BZ #12868]
 	* sysdeps/unix/sysv/linux/linux_fsinfo.h: Define Lustre constants.
 	* sysdeps/unix/sysv/linux/internal_statvfs.c (__statvfs_getflags):
diff --git a/sysdeps/unix/sysv/linux/fpathconf.c b/sysdeps/unix/sysv/linux/fpathconf.c
index 617a5a9..12a1e32 100644
--- a/sysdeps/unix/sysv/linux/fpathconf.c
+++ b/sysdeps/unix/sysv/linux/fpathconf.c
@@ -1,5 +1,5 @@
 /* Get file-specific information about descriptor FD.  Linux version.
-   Copyright (C) 1991,1995,1996,1998-2003,2008,2010
+   Copyright (C) 1991,1995,1996,1998-2003,2008,2010,2011
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -40,7 +40,7 @@ __fpathconf (fd, name)
   switch (name)
     {
     case _PC_LINK_MAX:
-      return __statfs_link_max (__fstatfs (fd, &fsbuf), &fsbuf);
+      return __statfs_link_max (__fstatfs (fd, &fsbuf), &fsbuf, NULL, fd);
 
     case _PC_FILESIZEBITS:
       return __statfs_filesize_max (__fstatfs (fd, &fsbuf), &fsbuf);
diff --git a/sysdeps/unix/sysv/linux/pathconf.c b/sysdeps/unix/sysv/linux/pathconf.c
index 42b7b80..1859314 100644
--- a/sysdeps/unix/sysv/linux/pathconf.c
+++ b/sysdeps/unix/sysv/linux/pathconf.c
@@ -17,8 +17,11 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <unistd.h>
 #include <errno.h>
+#include <mntent.h>
+#include <stdio_ext.h>
+#include <unistd.h>
+#include <sys/sysmacros.h>
 
 #include "pathconf.h"
 #include "linux_fsinfo.h"
@@ -42,7 +45,7 @@ __pathconf (const char *file, int name)
   switch (name)
     {
     case _PC_LINK_MAX:
-      return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf);
+      return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf, file, -1);
 
     case _PC_FILESIZEBITS:
       return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
@@ -74,9 +77,77 @@ __pathconf (const char *file, int name)
 }
 
 
+static long int
+distinguish_extX (const struct statfs *fsbuf, const char *file, int fd)
+{
+  char buf[64];
+  char path[PATH_MAX];
+  struct stat64 st;
+
+  if ((file == NULL ? fstat64 (fd, &st) : stat64 (file, &st)) != 0)
+    /* Strange.  The statfd call worked, but stat fails.  Default to
+       the more pessimistic value.  */
+    return EXT2_LINK_MAX;
+
+  __snprintf (buf, sizeof (buf), "/sys/dev/block/%u:%u",
+	      gnu_dev_major (st.st_dev), gnu_dev_minor (st.st_dev));
+
+  ssize_t n = __readlink (buf, path, sizeof (path));
+  if (n != -1 && n < sizeof (path))
+    {
+      path[n] = '\0';
+      char *base = strdupa (basename (path));
+      __snprintf (path, sizeof (path), "/sys/fs/ext4/%s", base);
+
+      return __access (path, F_OK) == 0 ? EXT4_LINK_MAX : EXT2_LINK_MAX;
+    }
+
+  /* XXX Is there a better way to distinguish ext2/3 from ext4 than
+     iterating over the mounted filesystems and compare the device
+     numbers?  */
+  FILE *mtab = __setmntent ("/proc/mounts", "r");
+  if (mtab == NULL)
+    mtab = __setmntent (_PATH_MOUNTED, "r");
+
+  /* By default be conservative.  */
+  long int result = EXT2_LINK_MAX;
+  if (mtab != NULL)
+    {
+      struct mntent mntbuf;
+      char tmpbuf[1024];
+
+      /* No locking needed.  */
+      (void) __fsetlocking (mtab, FSETLOCKING_BYCALLER);
+
+      while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
+	{
+	  if (strcmp (mntbuf.mnt_type, "ext2") != 0
+	      && strcmp (mntbuf.mnt_type, "ext3") != 0
+	      && strcmp (mntbuf.mnt_type, "ext4") != 0)
+	    continue;
+
+	  struct stat64 fsst;
+	  if (stat64 (mntbuf.mnt_dir, &fsst) >= 0
+	      && st.st_dev == fsst.st_dev)
+	    {
+	      if (strcmp (mntbuf.mnt_type, "ext4") == 0)
+		result = EXT4_LINK_MAX;
+	      break;
+	    }
+	}
+
+      /* Close the file.  */
+      __endmntent (mtab);
+    }
+
+  return result;
+}
+
+
 /* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
 long int
-__statfs_link_max (int result, const struct statfs *fsbuf)
+__statfs_link_max (int result, const struct statfs *fsbuf, const char *file,
+		   int fd)
 {
   if (result < 0)
     {
@@ -91,7 +162,11 @@ __statfs_link_max (int result, const struct statfs *fsbuf)
   switch (fsbuf->f_type)
     {
     case EXT2_SUPER_MAGIC:
-      return EXT2_LINK_MAX;
+      /* Unfortunately the kernel does not return a different magic number
+	 for ext4.  This would be necessary to easily detect etx4 since it
+	 has a different LINK_MAX value.  Therefore we have to find it out
+	 the hard way.  */
+      return distinguish_extX (fsbuf, file, fd);
 
     case MINIX_SUPER_MAGIC:
     case MINIX_SUPER_MAGIC2:
diff --git a/sysdeps/unix/sysv/linux/pathconf.h b/sysdeps/unix/sysv/linux/pathconf.h
index 806adcc..34289d8 100644
--- a/sysdeps/unix/sysv/linux/pathconf.h
+++ b/sysdeps/unix/sysv/linux/pathconf.h
@@ -1,5 +1,6 @@
 /* Common parts of Linux implementation of pathconf and fpathconf.
-   Copyright (C) 1991,1995,1996,1998-2003,2008 Free Software Foundation, Inc.
+   Copyright (C) 1991,1995,1996,1998-2003,2008,2011
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -22,8 +23,10 @@
 #include <sys/statfs.h>
 
 
-/* Used like: return __statfs_link_max (__statfs (name, &buf), &buf); */
-extern long int __statfs_link_max (int result, const struct statfs *fsbuf);
+/* Used like: return __statfs_link_max (__statfs (name, &buf), &buf,
+					name, -1); */
+extern long int __statfs_link_max (int result, const struct statfs *fsbuf,
+				   const char *file, int fd);
 
 
 /* Used like: return __statfs_filesize_max (__statfs (name, &buf), &buf); */

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                           |   10 ++++
 sysdeps/unix/sysv/linux/fpathconf.c |    4 +-
 sysdeps/unix/sysv/linux/pathconf.c  |   83 +++++++++++++++++++++++++++++++++--
 sysdeps/unix/sysv/linux/pathconf.h  |    9 +++-
 4 files changed, 97 insertions(+), 9 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]