Logo Search packages:      
Sourcecode: lfc version File versions  Download package

poolmgr.c

/*
 * Copyright (C) 2004-2008 by CERN/IT/GD/CT
 * All rights reserved
 */

#ifndef lint
static char sccsid[] = "@(#)$RCSfile: poolmgr.c,v $ $Revision: 1.25 $ $Date: 2008/08/28 08:27:41 $ CERN IT-GD/CT Jean-Philippe Baud";
#endif /* not lint */

#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include "Cthread_api.h"
#include "dpm.h"
#include "dpm_server.h"
#include "rfio_api.h"
#include "serrno.h"
#include "u64subr.h"

static int nbpool;
static struct gc_entry gc_entry[DPM_MAXNBPOOLS];
static int poolconf_mutex;
static struct dpm_pool *pools;
extern int Cgroupmatch (gid_t, int, gid_t *);
extern void *gcthread(void *);

static int
dpm_findpool(char *poolname)
{
      int i;

      for (i = 0; i < nbpool; i++) {
            if (strcmp ((pools + i)->poolname, poolname) == 0)
                  return (i);
      }
      return (-1);
}

static int
dpm_findfs(char *server, char *fs, int *pool_idx)
{
      struct dpm_fs *elemp;
      int i;
      int j;

      if (*pool_idx >= 0) {
            elemp = (pools + *pool_idx)->elemp;
            for (j = 0; j < (pools + *pool_idx)->nbelem; j++) {
                  if (strcmp (elemp->server, server) == 0 &&
                      strcmp (elemp->fs, fs) == 0) {
                        return (j);
                  }
                  elemp++;
            }
      }

      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (elemp->server, server) == 0 &&
                      strcmp (elemp->fs, fs) == 0) {
                        *pool_idx = i;
                        return (j);
                  }
                  elemp++;
            }
      }
      return (-1);
}

dpm_addfs2poolconf(struct dpm_fs *fs_entry)
{
      struct dpm_fs *elemp;
      char fs_path[CA_MAXHOSTNAMELEN+81];
      int pool_idx;
      int rc = -1;
      struct rfstatfs64 st;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((pool_idx = dpm_findpool (fs_entry->poolname)) < 0) {
            serrno = EINVAL;
            goto af_unlock;
      }
      if (dpm_findfs (fs_entry->server, fs_entry->fs, &pool_idx) >= 0) {
            serrno = EEXIST;
            goto af_unlock;
      }
      if ((elemp = realloc ((pools + pool_idx)->elemp,
          ((pools + pool_idx)->nbelem + 1) * sizeof(struct dpm_fs))) == NULL) {
            serrno = ENOMEM;
            goto af_unlock;
      }
      (pools + pool_idx)->elemp = elemp;
      elemp += (pools + pool_idx)->nbelem;
      (pools + pool_idx)->nbelem++;
      memcpy (elemp, fs_entry, sizeof(struct dpm_fs));
      rc = 0;
      if (elemp->status != FS_DISABLED) {
            sprintf (fs_path, "%s:%s", elemp->server, elemp->fs);
            if (rfio_statfs64 (fs_path, &st) < 0) {
                  dpmlogit ("dpm_addfs2poolconf", "%s: %s\n", fs_path,
                      rfio_serror ());
                  serrno = rfio_serrno ();
                  rc = -1;
                  (pools + pool_idx)->nbelem--;
            } else {
                  elemp->capacity = (u_signed64)st.totblks * (u_signed64)st.bsize;
                  elemp->free = (u_signed64)st.freeblks * (u_signed64)st.bsize;
                  if (elemp->status == 0) {
                        (pools + pool_idx)->capacity += elemp->capacity;
                        (pools + pool_idx)->free += elemp->free;
                  }
            }
      }
af_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_addpool2poolconf(struct dpm_pool *pool_entry)
{
      char func[21];
      int i;
      struct dpm_pool *poolp;
      int rc = -1;

      strcpy (func, "dpm_addpool2poolconf");
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if (dpm_findpool (pool_entry->poolname) >= 0) {
            serrno = EEXIST;
            goto ap_unlock;
      }
      for (i = 0; i < DPM_MAXNBPOOLS; i++) {
            if (gc_entry[i].status == 0) break;
      }
      if (i >= DPM_MAXNBPOOLS) {
            serrno = ENOMEM;
            goto ap_unlock;
      }
      if ((poolp = realloc (pools, 
          (nbpool + 1) * sizeof(struct dpm_pool))) == NULL) {
            serrno = ENOMEM;
            goto ap_unlock;
      }
      pools = poolp;
      poolp += nbpool;
      nbpool++;
      memcpy (poolp, pool_entry, sizeof(struct dpm_pool));
      gc_entry[i].gc_idx = i;
      strcpy (gc_entry[i].poolname, pool_entry->poolname);
      gc_entry[i].status = 1;
      rc = 0;
ap_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      if (rc == 0) {
            /* start Garbage Collector thread for this pool */

            if (Cthread_create (&gcthread, &gc_entry[i]) < 0) {
                  dpmlogit (func, DP002, "Cthread_create", sstrerror (serrno));
                  return (-1);
            }
            dpmlogit (func, "Garbage Collector thread for pool %s created\n",
                pool_entry->poolname);
      }
      return (rc);
}

dpm_enoughfreespace(poolname, which_thresh)
char *poolname;
int which_thresh;
{
      int pool_idx;
      struct dpm_pool *pool_p;
      int rc = 0;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((pool_idx = dpm_findpool (poolname)) < 0)
            goto ef_unlock;
      pool_p = pools + pool_idx;
      if (which_thresh) {
            if (pool_p->gc_start_thresh == 0 || pool_p->capacity == 0)
                  rc = 1;
            else
                  rc = (pool_p->free > 0 &&
                        (pool_p->free * 100) > (pool_p->capacity * pool_p->gc_start_thresh));
      } else
            rc = (pool_p->free > 0 &&
                  (pool_p->free * 100) > (pool_p->capacity * pool_p->gc_stop_thresh));
ef_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_get_def_lifetime(char *pfn, char *poolname)
{
      int def_lifetime = DEFAULT_LIFETIME;
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      char *p;

      if (poolname) {
            if (Cthread_mutex_lock (&poolconf_mutex) < 0)
                  return (def_lifetime);
            for (i = 0; i < nbpool; i++) {
                  if (strcmp ((pools + i)->poolname, poolname) == 0) {
                        def_lifetime = (pools + i)->def_lifetime;
                        break;
                  }
            }
            (void) Cthread_mutex_unlock (&poolconf_mutex);
            return (def_lifetime);
      }
      p = strchr (pfn, ':');
      if (p == NULL)
            return (def_lifetime);  /* cannot find the pool */
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (def_lifetime);
      *p = '\0';
      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (pfn, elemp->server) == 0 &&
                      strncmp (p + 1, elemp->fs, strlen (elemp->fs)) == 0 &&
                      *(p + 1 + strlen (elemp->fs)) == '/') {
                        def_lifetime = (pools + i)->def_lifetime;
                        found++;
                        break;
                  }
                  elemp++;
            }
            if (found) break;
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      *p = ':';
      return (def_lifetime);
}

dpm_get_defpintime(char *pfn)
{
      int defpintime = DEFAULT_PINTIME;
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      char *p;

      p = strchr (pfn, ':');
      if (p == NULL)
            return (defpintime);    /* cannot find the pool */
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (defpintime);
      *p = '\0';
      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (pfn, elemp->server) == 0 &&
                      strncmp (p + 1, elemp->fs, strlen (elemp->fs)) == 0 &&
                      *(p + 1 + strlen (elemp->fs)) == '/') {
                        defpintime = (pools + i)->defpintime;
                        found++;
                        break;
                  }
                  elemp++;
            }
            if (found) break;
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      *p = ':';
      return (defpintime);
}

dpm_get_fs_status (char *server, char *fs, int *status)
{
      struct dpm_fs *elemp;
      int fs_idx;
      int pool_idx = -1;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((fs_idx = dpm_findfs (server, fs, &pool_idx)) < 0) {
            (void) Cthread_mutex_unlock (&poolconf_mutex);
            return (-1);
      }
      elemp = (pools + pool_idx)->elemp + fs_idx;
      *status = elemp->status;
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (0);
}

dpm_get_max_lifetime(char *pfn)
{
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      int max_lifetime = MAX_LIFETIME;
      char *p;

      p = strchr (pfn, ':');
      if (p == NULL)
            return (max_lifetime);  /* cannot find the pool */
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (max_lifetime);
      *p = '\0';
      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (pfn, elemp->server) == 0 &&
                      strncmp (p + 1, elemp->fs, strlen (elemp->fs)) == 0 &&
                      *(p + 1 + strlen (elemp->fs)) == '/') {
                        max_lifetime = (pools + i)->max_lifetime;
                        found++;
                        break;
                  }
                  elemp++;
            }
            if (found) break;
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      *p = ':';
      return (max_lifetime);
}

dpm_get_maxpintime(char *pfn)
{
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      int maxpintime = MAX_PINTIME;
      char *p;

      p = strchr (pfn, ':');
      if (p == NULL)
            return (0); /* cannot find the pool */
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (maxpintime);
      *p = '\0';
      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (pfn, elemp->server) == 0 &&
                      strncmp (p + 1, elemp->fs, strlen (elemp->fs)) == 0 &&
                      *(p + 1 + strlen (elemp->fs)) == '/') {
                        maxpintime = (pools + i)->maxpintime;
                        found++;
                        break;
                  }
                  elemp++;
            }
            if (found) break;
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      *p = ':';
      return (maxpintime);
}

dpm_getpoolconf(struct dpm_dbfd *dbfd)
{
      int bof;
      int bol;
      int c;
      DBLISTPTR dblistptr;
      struct dpm_fs *elemp;
      struct dpm_fs fs_entry;
      char fs_path[CA_MAXHOSTNAMELEN+81];
      char func[16];
      int i;
      int j;
      int nbfs;
      struct dpm_pool pool_entry;
      struct rfstatfs64 st;
      char tmpbuf[21];
      char tmpbuf2[21];

      strcpy (func, "dpm_getpoolconf");

      /* count the number of disk pools already defined */

      dpmlogit (func, "getting existing disk pool configuration from the DB\n");
      bol = 1;
      while ((c = dpm_list_pool_entry (dbfd, bol, &pool_entry,
            0, &dblistptr)) == 0) {
            nbpool++;
            bol = 0;
      }
      (void) dpm_list_pool_entry (dbfd, bol, &pool_entry, 1, &dblistptr);
      if (c < 0)
            return (c);
      if (nbpool == 0)
            return (0);
      if ((pools = calloc (nbpool, sizeof(struct dpm_pool))) == NULL)
            return (-1);

      /* get the pool definitions */

      bol = 1;
      for (i = 0; i < nbpool; i++) {
            if ((c = dpm_list_pool_entry (dbfd, bol, pools + i, 0, &dblistptr)))
                  break;
            bol = 0;
      }
      (void) dpm_list_pool_entry (dbfd, bol, &pool_entry, 1, &dblistptr);
      if (c)
            return (c);

      /* get the pool members */

      for (i = 0; i < nbpool; i++) {
            dpmlogit (func, "POOL %s DEFSIZE %s\n", (pools + i)->poolname,
                u64tostru ((pools + i)->defsize, tmpbuf, 0));
            bof = 1;
            nbfs = 0;
            while ((c = dpm_list_fs_entry (dbfd, bof, (pools + i)->poolname,
                &fs_entry, 0, &dblistptr)) == 0) {
                  nbfs++;
                  bof = 0;
            }
            (void) dpm_list_fs_entry (dbfd, bof, (pools + i)->poolname,
                &fs_entry, 1, &dblistptr);
            if (c < 0)
                  return (c);
            if (nbfs == 0)
                  continue;

            if (((pools + i)->elemp = calloc (nbfs, sizeof(struct dpm_fs))) == NULL)
                  return (-1);
            (pools + i)->nbelem = nbfs;
            elemp = (pools + i)->elemp;

            bof = 1;
            for (j = 0; j < nbfs; j++) {
                  if ((c = dpm_list_fs_entry (dbfd, bof, (pools + i)->poolname,
                      elemp, 0, &dblistptr)))
                        break;
                  sprintf (fs_path, "%s:%s", elemp->server, elemp->fs);
                  if (elemp->status != FS_DISABLED) {
                        if (rfio_statfs64 (fs_path, &st) < 0) {
                              dpmlogit (func, "%s: %s\n", fs_path,
                                  rfio_serror ());
                              elemp->status = FS_DISABLED;
                        } else {
                              elemp->capacity = (u_signed64)st.totblks * (u_signed64)st.bsize;
                              elemp->free = (u_signed64)st.freeblks * (u_signed64)st.bsize;
                              if (elemp->status == 0) {
                                    (pools + i)->capacity += elemp->capacity;
                                    (pools + i)->free += elemp->free;
                              }
                        }
                  }
                  dpmlogit (func, ".... %s capacity=%s, free=%s, status=%d\n",
                      fs_path, u64tostru (elemp->capacity, tmpbuf, 0),
                      u64tostru (elemp->free, tmpbuf2, 0), elemp->status);
                  bof = 0;
                  elemp++;
            }
            (void) dpm_list_fs_entry (dbfd, bof, (pools + i)->poolname,
                &fs_entry, 1, &dblistptr);
            if (c)
                  return (c);

            /* start Garbage Collector thread for this pool */

            gc_entry[i].gc_idx = i;
            strcpy (gc_entry[i].poolname, (pools + i)->poolname);
            gc_entry[i].status = 1;
            if (Cthread_create (&gcthread, &gc_entry[i]) < 0) {
                  dpmlogit (func, DP002, "Cthread_create", sstrerror (serrno));
                  return (-1);
            }
            dpmlogit (func, "Garbage Collector thread for pool %s created\n",
                (pools + i)->poolname);
      }
      return (0);
}

dpm_getfsfrompoolconf(char *poolname, struct dpm_fs **elemp)
{
      int nbfs;
      int pool_idx;
      int rc = -1;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((pool_idx = dpm_findpool (poolname)) < 0) {
            serrno = EINVAL;
            goto gf_unlock;
      }
      nbfs = (pools + pool_idx)->nbelem;
      if (nbfs) {
            if ((*elemp = malloc (nbfs * sizeof(struct dpm_fs))) == NULL) {
                  serrno = ENOMEM;
                  goto gf_unlock;
            }
            memcpy (*elemp, (pools + pool_idx)->elemp, nbfs * sizeof(struct dpm_fs));
      }
      rc = nbfs;
gf_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_getpoolsfrompoolconf(struct dpm_pool **poolp)
{
      int rc = -1;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if (nbpool) {
            if ((*poolp = malloc (nbpool * sizeof(struct dpm_pool))) == NULL) {
                  serrno = ENOMEM;
                  goto gp_unlock;
            }
            memcpy (*poolp, pools, nbpool * sizeof(struct dpm_pool));
      }
      rc = nbpool;
gp_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_modfsinpoolconf (char *server, char *fs, int status)
{
      struct dpm_fs *elemp;
      int fs_idx;
      char fs_path[CA_MAXHOSTNAMELEN+81];
      int pool_idx = -1;
      int rc = -1;
      struct rfstatfs64 st;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((fs_idx = dpm_findfs (server, fs, &pool_idx)) < 0) {
            serrno = ENOENT;
            goto mf_unlock;
      }
      elemp = (pools + pool_idx)->elemp + fs_idx;
      rc = 0;
      if (status >= 0 && status != elemp->status) {
            if (status != FS_DISABLED) {
                  sprintf (fs_path, "%s:%s", elemp->server, elemp->fs);
                  if (rfio_statfs64 (fs_path, &st) < 0) {
                        dpmlogit ("dpm_modfsinpoolconf", "%s: %s\n", fs_path,
                            rfio_serror ());
                        serrno = rfio_serrno ();
                        rc = -1;
                        status = FS_DISABLED;
                  } else if (status == 0) {
                        elemp->capacity = (u_signed64)st.totblks * (u_signed64)st.bsize;
                        elemp->free = (u_signed64)st.freeblks * (u_signed64)st.bsize;
                  }
            }
            if (elemp->status && status == 0) {
                  (pools + pool_idx)->capacity += elemp->capacity;
                  (pools + pool_idx)->free += elemp->free;
            } else if (elemp->status == 0 && status) {
                  (pools + pool_idx)->capacity -= elemp->capacity;
                  (pools + pool_idx)->free -= elemp->free;
            }
            elemp->status = status;
      }
mf_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_modpoolinpoolconf (char *poolname, u_signed64 defsize, int gc_start_thresh, int gc_stop_thresh, int def_lifetime, int defpintime, int max_lifetime, int maxpintime, char *fss_policy, char *gc_policy, char *mig_policy, char *rs_policy, int pool_nbgids, gid_t *pool_gids, char ret_policy, char s_type)
{
      struct dpm_pool *poolp;
      int pool_idx;
      int rc = -1;
      int start_thresh;
      int stop_thresh;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((pool_idx = dpm_findpool (poolname)) < 0) {
            serrno = ENOENT;
            goto mp_unlock;
      }
      poolp = pools + pool_idx;
      if (gc_start_thresh != -1)
            start_thresh = gc_start_thresh;
      else
            start_thresh = poolp->gc_start_thresh;
      if (gc_stop_thresh != -1)
            stop_thresh = gc_stop_thresh;
      else
            stop_thresh = poolp->gc_stop_thresh;
      if (start_thresh > stop_thresh) {
            serrno = EINVAL;
            goto mp_unlock;
      }
      if (defsize != -1)
            poolp->defsize = defsize;
      if (gc_start_thresh != -1)
            poolp->gc_start_thresh = gc_start_thresh;
      if (gc_stop_thresh != -1)
            poolp->gc_stop_thresh = gc_stop_thresh;
      if (def_lifetime != -1)
            poolp->def_lifetime = def_lifetime;
      if (defpintime != -1)
            poolp->defpintime = defpintime;
      if (max_lifetime != -1)
            poolp->max_lifetime = max_lifetime;
      if (maxpintime != -1)
            poolp->maxpintime = maxpintime;
      if (*fss_policy)
            strcpy (poolp->fss_policy, fss_policy);
      if (*gc_policy)
            strcpy (poolp->gc_policy, gc_policy);
      if (*mig_policy)
            strcpy (poolp->mig_policy, mig_policy);
      if (*rs_policy)
            strcpy (poolp->rs_policy, rs_policy);
      if (pool_nbgids != -1) {
            free (poolp->gids);
            poolp->nbgids = pool_nbgids;
            poolp->gids = pool_gids;
      }
      if (ret_policy)
            poolp->ret_policy = ret_policy;
      if (s_type)
            poolp->s_type = s_type;
      rc = 0;
mp_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_reset_gc_entry(int gc_idx)
{
      memset (&gc_entry[gc_idx], 0, sizeof(struct gc_entry));
      return (0);
}

dpm_rmfsfrompoolconf(char *server, char *fs)
{
      struct dpm_fs *elemp;
      int fs_idx;
      int pool_idx = -1;
      int rc = -1;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((fs_idx = dpm_findfs (server, fs, &pool_idx)) < 0) {
            serrno = ENOENT;
            goto rf_unlock;
      }
      (pools + pool_idx)->nbelem--;
      if ((pools + pool_idx)->nbelem == 0) {
            free ((pools + pool_idx)->elemp);
            (pools + pool_idx)->capacity = 0;
            (pools + pool_idx)->free = 0;
            (pools + pool_idx)->elemp = NULL;
      } else {
            elemp = (pools + pool_idx)->elemp + fs_idx;
            if (elemp->status == 0) {
                  (pools + pool_idx)->capacity -= elemp->capacity;
                  (pools + pool_idx)->free -= elemp->free;
            }
            if (fs_idx < (pools + pool_idx)->nbelem)
                  memmove (elemp, elemp + 1,
                      ((pools + pool_idx)->nbelem - fs_idx) * sizeof(struct dpm_fs));
            if ((elemp = realloc ((pools + pool_idx)->elemp,
                (pools + pool_idx)->nbelem * sizeof(struct dpm_fs))))
                  (pools + pool_idx)->elemp = elemp;
      }
      rc = 0;
rf_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

dpm_rmpoolfrompoolconf(char *poolname)
{
      int pool_idx;
      struct dpm_pool *poolp;
      int rc = -1;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      if ((pool_idx = dpm_findpool (poolname)) < 0) {
            serrno = ENOENT;
            goto rp_unlock;
      }
      if ((pools + pool_idx)->nbelem) {
            serrno = EEXIST;
            goto rp_unlock;
      }
      free ((pools + pool_idx)->gids);
      nbpool--;
      if (nbpool == 0) {
            free (pools);
            pools = NULL;
      } else {
            if (pool_idx < nbpool)
                  memmove (pools + pool_idx, pools + pool_idx + 1,
                      (nbpool - pool_idx) * sizeof(struct dpm_pool));
            if ((poolp = realloc (pools, nbpool * sizeof(struct dpm_pool))))
                  pools = poolp;
      }
      rc = 0;
rp_unlock:
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (rc);
}

      /* Round-Robin allocation as long as there is enough free space */
      /* must be at least min_free percent of the capacity remaing if the file was added */

dpm_selectfsinpool(int pool_idx, char **excl_host, char **excl_fs, u_signed64 *size, int *fs_idx, int min_free)
{
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      struct dpm_pool *poolp;
      u_signed64 reqsize;

      poolp = pools + pool_idx;
      if (*size == 0)
            reqsize = poolp->defsize;
      else
            reqsize = *size;
      i = poolp->next_elem;
      do {
            elemp = poolp->elemp + i;
            if (excl_host) {
                  j = 0;
                  while (excl_host[j]) {
                        if (strcmp (elemp->server, excl_host[j]) == 0 &&
                            strcmp (elemp->fs, excl_fs[j]) == 0) break;
                        j++;
                  }
            }
            if (! excl_host || ! excl_host[j])
                  if (elemp->status == 0 && elemp->free > 0 &&
                      elemp->free >= reqsize &&
                      ((elemp->free - reqsize) * 100) >= (elemp->capacity * min_free)) {
                        found = 1;
                        break;
                  }
            i++;
            if (i >= poolp->nbelem) i = 0;
      } while (i != poolp->next_elem);
      if (! found)
            return (-1);

      poolp->next_elem = i + 1;
      if (poolp->next_elem >= poolp->nbelem) poolp->next_elem = 0;
      *size = reqsize;
      *fs_idx = i;
      return (0);
}

dpm_poolmatch (gid_t gid, char f_type, char rp_op, char ret_policy, u_signed64 reqsize, int *pool_idx)
{
      int i;

      for (i = 0; i < nbpool; i++) {
            if (Cgroupmatch (gid, (pools + i)->nbgids, (pools + i)->gids) &&
                ((pools + i)->s_type == f_type || f_type == '-') &&
                ((rp_op == '=' && (pools + i)->ret_policy == ret_policy) ||
                 (rp_op == '<' && (pools + i)->ret_policy < ret_policy)) &&
                (pools + i)->capacity && (pools + i)->free > 0 &&
                (pools + i)->free >= reqsize)
                  break;
      }
      if (i < nbpool) {
            *pool_idx = i;
            return (1);
      }
      return (0); /* no matching pool */
}

dpm_poolmatch2(gid_t gid, char f_type, char rp_op, char ret_policy, char **excl_host, char **excl_fs, u_signed64 *size, int *pool_idx, int *fs_idx, int min_free)
{
      int i;

      for (i = 0; i < nbpool; i++) {
            if (Cgroupmatch (gid, (pools + i)->nbgids, (pools + i)->gids) &&
                (pools + i)->s_type == f_type &&
                ((rp_op == '=' && (pools + i)->ret_policy == ret_policy) ||
                 (rp_op == '<' && (pools + i)->ret_policy < ret_policy)) &&
                (pools + i)->free > 0 &&
                dpm_selectfsinpool (i, excl_host, excl_fs, size, fs_idx, min_free) == 0)
                  break;
      }
      if (i < nbpool) {
            *pool_idx = i;
            return (1);
      }
      return (0); /* no matching pool */
}

dpm_selectfs(gid_t gid, char f_type, char ret_policy, char ac_latency, char **excl_host, char **excl_fs, u_signed64 *size, char *server, char *pfn, char *poolname, int *defpintime)
{
      struct dpm_fs *elemp;
      int i;
      int ipass;
      int j;
      int min_free;
      struct dpm_pool *poolp;
      char tmpbuf0[21];
      char tmpbuf1[21];
      char tmpbuf2[21];

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);

      if (! *poolname) {      /* Select pool in default space */
            for (ipass = 0; ipass < 2; ipass++) {
                  switch (ipass) {
                        case 0:
                              min_free = 2;
                              break;
                        case 1:
                              min_free = 0;
                              break;
                  }
                  if (dpm_poolmatch2 (gid, f_type, '=', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (gid, f_type, '<', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (gid, '-', '=', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (gid, '-', '<', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (0, f_type, '=', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (0, f_type, '<', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (0, '-', '=', ret_policy, excl_host, excl_fs, size, &i, &j, min_free) ||
                      dpm_poolmatch2 (0, '-', '<', ret_policy, excl_host, excl_fs, size, &i, &j, min_free)) {
                        break;
                  }
            }
            if (ipass >= 2) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = ENOSPC;
                  return (-1);
            }
      } else {    /* pool name is associated with space token */
            for (i = 0; i < nbpool; i++) {
                  if (strcmp ((pools + i)->poolname, poolname) == 0 &&
                      (pools + i)->capacity)
                        break;
            }
            if (i >= nbpool) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = EINVAL;
                  return (-1);
            }
            if (dpm_selectfsinpool (i, excl_host, excl_fs, size, &j, 2) < 0 &&
                dpm_selectfsinpool (i, excl_host, excl_fs, size, &j, 0) < 0) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = ENOSPC;
                  return (-1);
            }
      }

      poolp = pools + i;
      elemp = poolp->elemp + j;
      elemp->free -= *size;
      if (! *poolname)
            poolp->free -= *size;
      strcpy (server, elemp->server);
      sprintf (pfn, "%s:%s", elemp->server, elemp->fs);
      if (! *poolname)
            strcpy (poolname, poolp->poolname);
      *defpintime = poolp->defpintime;
      dpmlogit ("dpm_selectfs", "selected pool: %s\n", poolp->poolname);
      dpmlogit ("dpm_selectfs", "selected file system: %s\n", pfn);
      dpmlogit ("dpm_selectfs", "%s reqsize=%s, elemp->free=%s, poolp->free=%s\n",
          pfn, u64tostr (*size, tmpbuf0, 0), i64tostr(elemp->free, tmpbuf1, 0),
          i64tostr(poolp->free, tmpbuf2, 0));
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (0);
}

dpm_selectpool(gid_t gid, char f_type, char ret_policy, char ac_latency, u_signed64 reqsize, char *poolname, char *errstring)
{
      int i;
      struct dpm_pool *poolp;
      char tmpbuf0[21];
      char tmpbuf1[21];

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);

      if (! *poolname) {      /* Select pool according to gid, space type and retention policy */
            if (! dpm_poolmatch (gid, f_type, '=', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (gid, f_type, '<', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (gid, '-', '=', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (gid, '-', '<', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (0, f_type, '=', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (0, f_type, '<', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (0, '-', '=', ret_policy, reqsize, &i) &&
                ! dpm_poolmatch (0, '-', '<', ret_policy, reqsize, &i)) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = ENOSPC;
                  return (-1);
            }
      } else {    /* space reservation is for a specific pool or being extended */
            for (i = 0; i < nbpool; i++) {
                  if (strcmp ((pools + i)->poolname, poolname) == 0)
                        break;
            }
            if (i >= nbpool) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  strcpy (errstring, "Unknown pool");
                  serrno = EINVAL;
                  return (-1);
            }
            if ((pools + i)->gids[0] &&
                Cgroupmatch (gid, (pools + i)->nbgids, (pools + i)->gids) == 0 && gid != 0) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = EACCES;
                  return (-1);
            }
            if ((pools + i)->capacity <= 0 || (pools + i)->free < 0 ||
                (pools + i)->free < reqsize) {
                  (void) Cthread_mutex_unlock (&poolconf_mutex);
                  serrno = ENOSPC;
                  return (-1);
            }
      }
      poolp = pools + i;
      poolp->free -= reqsize;
      if (! *poolname)
            strcpy (poolname, poolp->poolname);
      dpmlogit ("dpm_selectpool", "selected pool: %s\n", poolp->poolname);
      dpmlogit ("dpm_selectpool", "reqsize=%s, poolp->free=%s\n",
          u64tostr (reqsize, tmpbuf0, 0), i64tostr(poolp->free, tmpbuf1, 0));
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (0);
}

dpm_stop_gc(char *poolname)
{
      int i;

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      for (i = 0; i < DPM_MAXNBPOOLS; i++) {
            if (strcmp (gc_entry[i].poolname, poolname) == 0) break;
      }
      if (i >= DPM_MAXNBPOOLS) {
            (void) Cthread_mutex_unlock (&poolconf_mutex);
            return (-1);
      }
      gc_entry[i].status = 2;
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (0);
}

dpm_updfreespace(char *pfn, signed64 incr, char *s_token, int flag)
{
      struct dpm_fs *elemp;
      int found = 0;
      int i;
      int j;
      char *p;
      char tmpbuf0[21];
      char tmpbuf1[21];
      char tmpbuf2[21];

      p = strchr (pfn, ':');
      if (p == NULL)
            return (0); /* cannot find the pool */
      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);
      *p = '\0';
      for (i = 0; i < nbpool; i++) {
            elemp = (pools + i)->elemp;
            for (j = 0; j < (pools + i)->nbelem; j++) {
                  if (strcmp (pfn, elemp->server) == 0 &&
                      strncmp (p + 1, elemp->fs, strlen (elemp->fs)) == 0 &&
                      (*(p + 1 + strlen (elemp->fs)) == '/' ||
                       *(p + 1 + strlen (elemp->fs)) == '\0')) {
                        found++;
                        break;
                  }
                  elemp++;
            }
            if (found) break;
      }

      if (found) {
            elemp->free += incr;
            if (! *s_token && elemp->status == 0)
                  (pools + i)->free += incr;
            else if (*s_token && elemp->status != 0 && flag)
                  (pools + i)->free -= incr;
            dpmlogit ("dpm_updfreespace", "%s:%s incr=%s, elemp->free=%s, poolp->free=%s\n",
                elemp->server, elemp->fs, i64tostr (incr, tmpbuf0, 0),
                i64tostr(elemp->free, tmpbuf1, 0), i64tostr((pools + i)->free, tmpbuf2, 0));
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      *p = ':';
      return (0);
}

dpm_updpoolfreespace(char *poolname, signed64 incr)
{
      int found = 0;
      int i;
      char tmpbuf0[21];
      char tmpbuf1[21];

      if (Cthread_mutex_lock (&poolconf_mutex) < 0)
            return (-1);

      for (i = 0; i < nbpool; i++) {
            if (strcmp ((pools + i)->poolname, poolname) == 0) {
                  found++;
                  break;
            }
      }
      if (found) {
            (pools + i)->free += incr;
            dpmlogit ("dpm_updpoolfreespace", "%s incr=%s, poolp->free=%s\n",
                poolname, i64tostr (incr, tmpbuf0, 0), i64tostr((pools+i)->free, tmpbuf1, 0));
      }
      (void) Cthread_mutex_unlock (&poolconf_mutex);
      return (0);
}

dpm_wait4allgcs()
{
      int i;
      int nbgcs;

      while (1) {
            nbgcs = 0;
            for (i = 0; i < nbpool; i++) {
                  if (gc_entry[i].status)
                        nbgcs++;
            }
            if (nbgcs == 0) break;
            sleep (1);
      }
      return (0);
}

Generated by  Doxygen 1.6.0   Back to index