[libmultipath] fix the "too many files" error
authorBenjamin Marzinski <bmarzin@redhat.com>
Tue, 15 Jan 2008 22:59:04 +0000 (23:59 +0100)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Tue, 15 Jan 2008 22:59:04 +0000 (23:59 +0100)
Added a max_fds parameter to /etc/multipath.conf. This allows
you to set the maximum number of open fds that multipathd can use, like with
ulimit -n.  Also added some code so that multipath closes the file descriptor
after it's used by the checker function, since multipath doesn't need to keep
them always open like multipathd does.

libmultipath/config.c
libmultipath/config.h
libmultipath/dict.c
libmultipath/discovery.c
libmultipath/structs.h
multipath.conf.annotated
multipath.conf.synthetic
multipathd/main.c

index 619b6e7..b6d4fb9 100644 (file)
@@ -354,6 +354,7 @@ load_config (char * file)
 
        conf->dev_type = DEV_NONE;
        conf->minio = 1000;
+       conf->max_fds = 0;
        conf->bindings_file = DEFAULT_BINDINGS_FILE;
 
        /*
index 7f7b2a9..7568d7b 100644 (file)
@@ -66,6 +66,7 @@ struct config {
        int no_path_retry;
        int user_friendly_names;
        int pg_timeout;
+       int max_fds;
 
        char * dev;
        char * sysfs_dir;
index 6ed5cfd..fa37ee8 100644 (file)
@@ -140,6 +140,26 @@ def_minio_handler(vector strvec)
 }
 
 static int
+max_fds_handler(vector strvec)
+{
+       char * buff;
+
+       buff = set_value(strvec);
+
+       if (!buff)
+               return 1;
+
+       if (strlen(buff) == 9 &&
+           !strcmp(buff, "unlimited"))
+               conf->max_fds = MAX_FDS_UNLIMITED;
+       else
+               conf->max_fds = atoi(buff);
+       FREE(buff);
+
+       return 0;
+}
+
+static int
 def_weight_handler(vector strvec)
 {
        char * buff;
@@ -1416,6 +1436,17 @@ snprint_def_rr_min_io (char * buff, int len, void * data)
 }
 
 static int
+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);
+}
+
+static int
 snprint_def_rr_weight (char * buff, int len, void * data)
 {
        if (!conf->rr_weight)
@@ -1516,6 +1547,7 @@ init_keywords(void)
        install_keyword("path_checker", &def_path_checker_handler, &snprint_def_path_checker);
        install_keyword("failback", &default_failback_handler, &snprint_def_failback);
        install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io);
+       install_keyword("max_fds", &max_fds_handler, &snprint_max_fds);
        install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight);
        install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry);
        install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout);
index 805d0b6..a85a248 100644 (file)
@@ -714,6 +714,10 @@ pathinfo (struct path *pp, vector hwtable, int mask)
        if (mask & DI_WWID && !strlen(pp->wwid))
                get_uid(pp);
 
+#ifndef DAEMON
+       close(pp->fd);
+       pp->fd = -1;
+#endif
        return 0;
 
 blank:
@@ -722,5 +726,11 @@ blank:
         */
        memset(pp->wwid, 0, WWID_SIZE);
        pp->state = PATH_DOWN;
+#ifndef DAEMON
+       if (pp->fd > 0){
+               close(pp->fd);
+               pp->fd = -1;
+       }
+#endif
        return 0;
 }
index 8e9ac86..2517782 100644 (file)
@@ -21,6 +21,8 @@
 #define NO_PATH_RETRY_FAIL     -1
 #define NO_PATH_RETRY_QUEUE    -2
 
+#define MAX_FDS_UNLIMITED      -1
+
 enum free_path_switch {
        KEEP_PATHS,
        FREE_PATHS
index f617876..dc7af77 100644 (file)
 #      rr_min_io       100
 #
 #      #
+#      # name    : max_fds
+#      # scope   : multipathd
+#      # desc    : Sets the maximum number of open file descriptors for the
+#      #           multipathd process.
+#      # values  : unlimited|n > 0
+#      # default : None
+#      #
+#      max_fds         8192
+#
+#      #
 #      # name    : rr_weight
 #      # scope   : multipath
 #      # desc    : if set to priorities the multipath configurator will assign
index 0c05b4c..33f820b 100644 (file)
@@ -11,6 +11,7 @@
 #      prio                    const
 #      path_checker            directio
 #      rr_min_io               100
+#      max_fds                 8192
 #      rr_weight               priorities
 #      failback                immediate
 #      no_path_retry           fail
index e65834a..d30ba83 100644 (file)
@@ -12,6 +12,8 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 /*
  * libcheckers
@@ -1283,6 +1285,21 @@ child (void * param)
                conf->max_checkint = MAX_CHECKINT(conf->checkint);
        }
 
+       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;
+               }
+               if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
+                       condlog(0, "can't set open fds limit to %d : %s\n",
+                               conf->max_fds, strerror(errno));
+       }
+
        if (pidfile_create(DEFAULT_PIDFILE, getpid())) {
                if (logsink)
                        log_thread_stop();