multipath-tools: Improvement to max_fds
authorBenjamin Marzinski <bmarzins@redhat.com>
Thu, 14 May 2009 04:38:28 +0000 (23:38 -0500)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Thu, 14 May 2009 21:02:08 +0000 (23:02 +0200)
Setting max_fds to unlimited doesn't actually work.  In the kernel, there is a
fixed limit to the maximum number of open fds a process can have.  If you try
to set max_fds to greater than this, it fails.  This patch replaces the special
value "unlimited" with a new special value, "max".  If you set max_fds to "max",
multipath will use the actual system limit, which it looks up from
/proc/sys/fs/nr_open.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
libmultipath/dict.c
libmultipath/structs.h
multipath.conf.annotated
multipath/main.c
multipath/multipath.conf.5
multipathd/main.c

index 2902e89..ee4de68 100644 (file)
@@ -19,6 +19,7 @@
 #include "blacklist.h"
 #include "defaults.h"
 #include "prio.h"
+#include "errno.h"
 
 /*
  * default block handlers
@@ -156,23 +157,52 @@ def_minio_handler(vector strvec)
 }
 
 static int
+get_sys_max_fds(int *max_fds)
+{
+       FILE *file;
+       int nr_open;
+       int ret = 1;
+
+       file = fopen("/proc/sys/fs/nr_open", "r");
+       if (!file) {
+               fprintf(stderr, "Cannot open /proc/sys/fs/nr_open : %s\n",
+                       strerror(errno));
+               return 1;
+       }
+       if (fscanf(file, "%d", &nr_open) != 1) {
+               fprintf(stderr, "Cannot read max open fds from /proc/sys/fs/nr_open");
+               if (ferror(file))
+                       fprintf(stderr, " : %s\n", strerror(errno));
+               else
+                       fprintf(stderr, "\n");
+       } else {
+               *max_fds = nr_open;
+               ret = 0;
+       }
+       fclose(file);
+       return ret;
+}
+
+
+static int
 max_fds_handler(vector strvec)
 {
        char * buff;
+       int r = 0;
 
        buff = set_value(strvec);
 
        if (!buff)
                return 1;
 
-       if (strlen(buff) == 9 &&
-           !strcmp(buff, "unlimited"))
-               conf->max_fds = MAX_FDS_UNLIMITED;
+       if (strlen(buff) == 3 &&
+           !strcmp(buff, "max"))
+               r = get_sys_max_fds(&conf->max_fds);
        else
                conf->max_fds = atoi(buff);
        FREE(buff);
 
-       return 0;
+       return r;
 }
 
 static int
@@ -1755,8 +1785,6 @@ snprint_max_fds (char * buff, int len, void * data)
        if (!conf->max_fds)
                return 0;
 
-       if (conf->max_fds < 0)
-               return snprintf(buff, len, "unlimited");
        return snprintf(buff, len, "%d", conf->max_fds);
 }
 
index f7eca60..aafadba 100644 (file)
@@ -24,7 +24,6 @@
 #define NO_PATH_RETRY_FAIL     -1
 #define NO_PATH_RETRY_QUEUE    -2
 
-#define MAX_FDS_UNLIMITED      -1
 
 enum free_path_switch {
        KEEP_PATHS,
index 1b8f7cc..2374d56 100644 (file)
 #      # scope   : multipathd
 #      # desc    : Sets the maximum number of open file descriptors for the
 #      #           multipathd process.
-#      # values  : unlimited|n > 0
+#      # values  : max|n > 0
 #      # default : None
 #      #
 #      max_fds         8192
index 707e2b9..d72e242 100644 (file)
@@ -428,14 +428,9 @@ main (int argc, char *argv[])
 
        if (conf->max_fds) {
                struct rlimit fd_limit;
-               if (conf->max_fds > 0) {
-                       fd_limit.rlim_cur = conf->max_fds;
-                       fd_limit.rlim_max = conf->max_fds;
-               }
-               else {
-                       fd_limit.rlim_cur = RLIM_INFINITY;
-                       fd_limit.rlim_max = RLIM_INFINITY;
-               }
+
+               fd_limit.rlim_cur = conf->max_fds;
+               fd_limit.rlim_max = conf->max_fds;
                if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
                        condlog(0, "can't set open fds limit to %d : %s\n",
                                conf->max_fds, strerror(errno));
index 6b1be81..df1f3b4 100644 (file)
@@ -230,6 +230,14 @@ use the WWID as the alias. In either case this be will
 be overriden by any specific aliases in the \fImultipaths\fR section.
 Default is
 .I no
+.TP
+.B max_fds
+Specify the maximum number of file descriptors that can be opened by multipath
+and multipathd.  This is equivalent to ulimit -n. A value of \fImax\fR will set
+this to the system limit from /proc/sys/fs/nr_open. If this is not set, the
+maximum number of open fds is taken from the calling process. It is usually
+1024. To be safe, this should be set to the maximum number of paths plus 32,
+if that number is greated than 1024.
 .
 .SH "blacklist section"
 The
index dfa1098..41a9bd0 100644 (file)
@@ -1373,14 +1373,9 @@ child (void * param)
 
        if (conf->max_fds) {
                struct rlimit fd_limit;
-               if (conf->max_fds > 0) {
-                       fd_limit.rlim_cur = conf->max_fds;
-                       fd_limit.rlim_max = conf->max_fds;
-               }
-               else {
-                       fd_limit.rlim_cur = RLIM_INFINITY;
-                       fd_limit.rlim_max = RLIM_INFINITY;
-               }
+
+               fd_limit.rlim_cur = conf->max_fds;
+               fd_limit.rlim_max = conf->max_fds;
                if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
                        condlog(0, "can't set open fds limit to %d : %s\n",
                                conf->max_fds, strerror(errno));