Add support for prlimit and prlimit64 on Linux.
authorUlrich Drepper <drepper@redhat.com>
Wed, 11 Aug 2010 18:18:52 +0000 (11:18 -0700)
committerUlrich Drepper <drepper@redhat.com>
Wed, 11 Aug 2010 18:18:52 +0000 (11:18 -0700)
12 files changed:
ChangeLog
NEWS
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/Versions
sysdeps/unix/sysv/linux/bits/resource.h
sysdeps/unix/sysv/linux/i386/syscalls.list
sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list
sysdeps/unix/sysv/linux/prlimit.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list
sysdeps/unix/sysv/linux/sh/syscalls.list
sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list
sysdeps/unix/sysv/linux/wordsize-64/syscalls.list

index 96655d8..30b59e6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2010-08-11  Ulrich Drepper  <drepper@redhat.com>
 
+       * sysdeps/unix/sysv/linux/Makefile [subdir=misc] (sysdep_routines):
+       Add prlimit.
+       * sysdeps/unix/sysv/linux/Versions [libc]: Export prlimit and
+       prlimit64 for GLIBC_2.13.
+       * sysdeps/unix/sysv/linux/bits/resource.h: Declare prlimit and
+       prlimit64.
+       * sysdeps/unix/sysv/linux/i386/syscalls.list: Add entry for prlimit64
+       syscall.
+       * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list: Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list: Likewise.
+       * sysdeps/unix/sysv/linux/sh/syscalls.list: Likewise.
+       * sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.lis: Likewise.
+       * sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: Likewise.  Also
+       add prlimit alias.
+       * sysdeps/unix/sysv/linux/prlimit.c: New file.
+
        [BZ #11903]
        * sysdeps/generic/netinet/ip.h (IPTOS_CLASS): Fix definition.
        Patch by Evgeni Bikov <bikovevg@iitp.ru>.
diff --git a/NEWS b/NEWS
index e51fba9..0e461c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ Version 2.13
 
   11640, 11701, 11840, 11856, 11883, 11903
 
+* New Linux interfaces: prlimit, prlimit64
+
 * POWER7 optimizations: memset, memcmp, strncmp
 
 * New optimized string functions for x86-64: strnlen, strcasecmp
index 9c53b2d..5ab6a4f 100644 (file)
@@ -18,7 +18,7 @@ endif
 ifeq ($(subdir),misc)
 sysdep_routines += sysctl clone llseek umount umount2 readahead \
                   setfsuid setfsgid makedev epoll_pwait signalfd \
-                  eventfd eventfd_read eventfd_write
+                  eventfd eventfd_read eventfd_write prlimit
 
 CFLAGS-gethostid.c = -fexceptions
 
index f09ef6d..c662765 100644 (file)
@@ -149,6 +149,9 @@ libc {
 
     recvmmsg;
   }
+  GLIBC_2.13 {
+    prlimit; prlimit64;
+  }
   GLIBC_PRIVATE {
     # functions used in other libraries
     __syscall_rt_sigqueueinfo;
index cb3acf1..ca2c9f0 100644 (file)
@@ -1,5 +1,5 @@
 /* Bit values & structures for resource limits.  Linux version.
-   Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005, 2008, 2009
+   Copyright (C) 1994, 1996-2000, 2004, 2005, 2008, 2009, 2010
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -232,3 +232,31 @@ enum __priority_which
   PRIO_USER = 2                        /* WHO is a user ID.  */
 #define PRIO_USER PRIO_USER
 };
+
+
+__BEGIN_DECLS
+
+#ifdef __USE_GNU
+/* Modify and return resource limits of a process atomically.  */
+# ifndef __USE_FILE_OFFSET64
+extern int prlimit (__pid_t __pid, enum __rlimit_resource __resource,
+                   __const struct rlimit *__new_limit,
+                   struct rlimit *__old_limit) __THROW;
+# else
+#  ifdef __REDIRECT_NTH
+extern int __REDIRECT_NTH (prlimit, (__pid_t __pid,
+                                    enum __rlimit_resource __resource,
+                                    __const struct rlimit *__new_limit,
+                                    struct rlimit *__old_limit), prlimit64);
+#  else
+#   define prlimit prlimit64
+#  endif
+# endif
+# ifdef __USE_LARGEFILE64
+extern int prlimit64 (__pid_t __pid, enum __rlimit_resource __resource,
+                     __const struct rlimit64 *__new_limit,
+                     struct rlimit64 *__old_limit) __THROW;
+# endif
+#endif
+
+__END_DECLS
index 3ff3a73..597e598 100644 (file)
@@ -6,3 +6,5 @@ vm86            -       vm86            i:ip    __vm86          vm86@@GLIBC_2.3.4
 oldgetrlimit   EXTRA   getrlimit       i:ip    __old_getrlimit getrlimit@GLIBC_2.0
 oldsetrlimit   EXTRA   setrlimit       i:ip    __old_setrlimit setrlimit@GLIBC_2.0
 waitpid                -       waitpid         Ci:ipi  __waitpid       waitpid __libc_waitpid
+
+prlimit64      EXTRA   prlimit64       i:iipp  prlimit64
index 1233be6..3012285 100644 (file)
@@ -6,3 +6,5 @@ oldsetrlimit    EXTRA   setrlimit       i:ip    __old_setrlimit setrlimit@GLIBC_2.0
 
 # Due to 64bit alignment there is a dummy second parameter
 readahead      -       readahead       i:iiiii __readahead     readahead
+
+prlimit64      EXTRA   prlimit64       i:iipp  prlimit64
diff --git a/sysdeps/unix/sysv/linux/prlimit.c b/sysdeps/unix/sysv/linux/prlimit.c
new file mode 100644 (file)
index 0000000..6d61e9a
--- /dev/null
@@ -0,0 +1,92 @@
+/* Copyright (C) 2010 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+
+
+#ifdef __NR_prlimit64
+int
+prlimit (__pid_t pid, enum __rlimit_resource resource,
+        __const struct rlimit *new_limit, struct rlimit *old_limit)
+{
+  struct rlimit64 new_rlimit64_mem;
+  struct rlimit64 *new_rlimit64 = NULL;
+  struct rlimit64 old_rlimit64_mem;
+  struct rlimit64 *old_rlimit64 = (old_rlimiit != NULL
+                                  ? &old_rlimit64_mem : NULL);
+
+  if (new_rlimit != NULL)
+    {
+      if (new_rlimit->rlim_cur == RLIM_INFINITY)
+       new_rlimit64_mem.rlim_cur = RLIM64_INFINITY;
+      else
+       new_rlimit64_mem.rlim_cur = new_rlimit->rlim_cur;
+      if (new_rlimit->rlim_max == RLIM_INFINITY)
+       new_rlimit64_mem.rlim_max =  = RLIM64_INFINITY;
+      else
+       new_rlimit64_mem.rlim_max = new_rlimit->rlim_max;
+      new_rlimit64 = &new_rlimit64_mem;
+    }
+
+  int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64,
+                           old_rlimit64);
+
+  if (res == 0 && old_limit != NULL)
+    {
+      /* The prlimit64 syscall is ill-designed for 32-bit machines.
+        We have to provide a 32-bit variant since otherwise the LFS
+        system would not work.  But what shall we do if the syscall
+        succeeds but the old values do not fit into a rlimit
+        structure?  We cannot return an error because the operation
+        itself worked.  Best is perhaps to return RLIM_INFINITY.  */
+      old_rlimit->rlim_cur = old_rlimit64_mem.rlim_cur;
+      if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur)
+       {
+         if (new_limit == NULL)
+           {
+             __set_errno (EOVERFLOW);
+             return -1;
+           }
+         old_rlimit->rlim_cur = RLIM_INFINITY;
+       }
+      old_rlimit->rlim_max = old_rlimit64_mem.rlim_max;
+      if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max)
+       {
+         if (new_limit == NULL)
+           {
+             __set_errno (EOVERFLOW);
+             return -1;
+           }
+         old_rlimit->rlim_max = RLIM_INFINITY;
+       }
+    }
+
+  return res;
+}
+#else
+int
+prlimit (__pid_t pid, enum __rlimit_resource resource,
+        __const struct rlimit *new_limit, struct rlimit *old_limit)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (prlimit)
+#endif
index 0e76857..d3a05d2 100644 (file)
@@ -3,3 +3,5 @@
 oldgetrlimit   EXTRA   getrlimit       i:ip    __old_getrlimit getrlimit@GLIBC_2.0
 oldsetrlimit   EXTRA   setrlimit       i:ip    __old_setrlimit setrlimit@GLIBC_2.0
 vfork          -       vfork           0       __vfork         vfork
+
+prlimit64      EXTRA   prlimit64       i:iipp  prlimit64
index a666593..be9ffed 100644 (file)
@@ -1,3 +1,5 @@
 # File name    Caller  Syscall name    # args  Strong name     Weak names
 
 waitpid                -       waitpid         Ci:ipi  __waitpid       waitpid __libc_waitpid
+
+prlimit64      EXTRA   prlimit64       i:iipp  prlimit64
index 2bfe376..8b1d682 100644 (file)
@@ -4,3 +4,5 @@ setrlimit       -       setrlimit       2       __setrlimit     setrlimit
 getrlimit      -       getrlimit       2       __getrlimit     getrlimit
 getresuid      -       getresuid32     3       getresuid
 getresgid      -       getresgid32     3       getresgid
+
+prlimit64      EXTRA   prlimit64       i:iipp  prlimit64
index 6091550..b2e2163 100644 (file)
@@ -17,3 +17,4 @@ sendfile      -       sendfile        i:iipi  sendfile        sendfile64
 sync_file_range        -       sync_file_range i:iiii  sync_file_range
 creat          -       creat           Ci:si   __libc_creat    creat creat64
 open           -       open            Ci:siv  __libc_open     __open open __open64 open64
+prlimit                EXTRA   prlimit64       i:iipp  prlimit         prlimit64