diff options
| author | Raghavendra G <rgowdapp@redhat.com> | 2013-09-16 17:46:50 +0530 | 
|---|---|---|
| committer | Anand Avati <avati@redhat.com> | 2013-11-26 10:24:02 -0800 | 
| commit | ab3ab1978a4768e9eed8e23b47e72b25046e607a (patch) | |
| tree | f4e8d1a5aecd24d45a9db531d658a947cd94261d /libglusterfs | |
| parent | 460ce40d3e2069bf6262dccea6f5ae2fac60d90f (diff) | |
features/quota: Improvements to quota
* Two stages of quota enforcement is done:
  Soft and hard quota Upon reaching soft quota limit on the directory
  it logs/alerts in the quota daemon log (ie DEFAULT_LOG_DIR/quotad.log)
  and no more writes allowed after hard
  quota limit. After reaching the soft-limit the daemon alerts the
  user/admin repeatively for every 'alert-time', which is
  configurable.
* Quota enforcer is moved to server-side.
  It  takes care of enforcing quota. Since enforcer doesn't have the
  cluster view, it relies on another service called
  quota-aggregator. Aggregator, on query can return the size of a
  directory based on the cluster view.
  Enforcer is always loaded in the server graph and is by passed if
  the feature is not enabled.
  Options specific to enforcer:
  server-quota - Specifies whether the feature is on/off. It is used
  to by pass the quota if turned off.
  deem-statfs - If set to on, it takes quota limits into consideration
  while estimating fs size. (df command). The algorithm followed is,
  i.   Adjust statvfs based on limit configured on root.
  ii.  If limit is set on the inode passed, use size/limits on that inode to
       populate statvfs. Otherwise, use size/limits configured on root.
  iii. Upon statvfs, update the ctx->size on the inode.
  iv.  Don't let DHT aggregate, instead take the maximum of the usages from the
       subvols of the DHT, since each of it contains the complete information.
  Enforcer also makes use of gfid-to-path conversion functionality to
  work correctly when a client like nfs predominently relies on
  nameless lookups.
* Quota Aggregator acts as a thin client to provide cluster view
  Its a lightweight *gluster client* process with no mount point,
  started upon enabling quota or restarting the volume. This is a
  single process run on each brick, which can answer queries on all
  volumes in the cluster. Its volfile stored in
  GLUSTERD_DEFAULT_WORKING_DIR/quotad/quotad.vol.
Credits:
Raghavendra Bhat        <rabhat@redhat.com>
Varun Shastry           <vshastry@redhat.com>
Shishir Gowda           <sgowda@redhat.com>
Kruthika Dhananjay      <kdhananj@redhat.com>
Brian Foster            <bfoster@redhat.com>
Krishnan Parthasarathi  <kparthas@redhat.com>
Change-Id: Id1cb25b414951da34c665a55f77385d482e0f9de
BUG: 969461
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-on: http://review.gluster.org/5952
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'libglusterfs')
| -rw-r--r-- | libglusterfs/src/common-utils.c | 110 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 20 | ||||
| -rw-r--r-- | libglusterfs/src/dict.c | 14 | ||||
| -rw-r--r-- | libglusterfs/src/dict.h | 3 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/inode.h | 3 | ||||
| -rw-r--r-- | libglusterfs/src/options.c | 3 | ||||
| -rw-r--r-- | libglusterfs/src/options.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.c | 1 | 
9 files changed, 151 insertions, 6 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 2b700af4e11..4af1b445433 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -787,12 +787,44 @@ gf_string2time (const char *str, uint32_t *n)          if (errno == 0)                  errno = old_errno; -        if (!((tail[0] == '\0') || +        if (((tail[0] == '\0') ||                ((tail[0] == 's') && (tail[1] == '\0')) ||                ((tail[0] == 's') && (tail[1] == 'e') &&  	       (tail[2] == 'c') && (tail[3] == '\0')))) +               goto out; + +        else if (((tail[0] == 'm') && (tail[1] == '\0')) || +                 ((tail[0] == 'm') && (tail[1] == 'i') && +                  (tail[2] == 'n') && (tail[3] == '\0'))) { +                value = value * GF_MINUTE_IN_SECONDS; +                goto out; +        } + +        else if (((tail[0] == 'h') && (tail[1] == '\0')) || +                 ((tail[0] == 'h') && (tail[1] == 'r') && +	         (tail[2] == '\0'))) { +                value = value * GF_HOUR_IN_SECONDS; +                goto out; +        } + +        else if (((tail[0] == 'd') && (tail[1] == '\0')) || +                 ((tail[0] == 'd') && (tail[1] == 'a') && +	         (tail[2] == 'y') && (tail[3] == 's') && +                 (tail[4] == '\0'))) { +                value = value * GF_DAY_IN_SECONDS; +                goto out; +        } + +        else if (((tail[0] == 'w') && (tail[1] == '\0')) || +                 ((tail[0] == 'w') && (tail[1] == 'k') && +	         (tail[2] == '\0'))) { +                value = value * GF_WEEK_IN_SECONDS; +                goto out; +        } else {                  return -1; +        } +out:          *n = value;          return 0; @@ -2294,6 +2326,9 @@ gf_canonicalize_path (char *path)          if (!path || *path != '/')                  goto out; +        if (!strcmp (path, "/")) +                return 0; +          tmppath = gf_strdup (path);          if (!tmppath)                  goto out; @@ -2818,7 +2853,6 @@ out:  } -  /* Sets log file path from user provided arguments */  int  gf_set_log_file_path (cmd_args_t *cmd_args) @@ -2956,6 +2990,76 @@ backtrace_symbols(void *const *trace, size_t len)  	}  	return ptr; -}  +}  #undef BELOW  #endif /* __NetBSD__ */ + +/* TODO: extract common code from gf_get_soft_limit and gf_get_hard_limit into a + * function + */ +int +gf_get_soft_limit (char *limit, char **soft_limit) +{ +        int   colon_count   = 0; +        int   i             = 0; +        int   len           = 0; +        char *sl            = NULL; + +        len = strlen (limit); +        for (i = 0; i < len; i++) { +                if (limit[i] == ':') +                        colon_count++; +                if (colon_count == 2) +                        break; +        } + +        if (colon_count != 2) { +                gf_log ("common-utils", GF_LOG_DEBUG, "Soft-limit absent"); +                return 0; +        } + +        sl = GF_CALLOC (len - i, sizeof (char), gf_common_mt_char); +        if (!sl) +                return -1; +        strncpy (sl, &limit[i+1], len - i - 1); +        *soft_limit = sl; + +        return 1; +} + +int +gf_get_hard_limit (char *limit, char **hard_limit) +{ +        int    i                 = 0; +        int    hlbegin           = 0; +        int    len               = 0; +        char  *hl                = NULL; + +        len = strlen (limit); + +        for (i = 0; i < len; i++) { +                if (limit[i] == ':') +                        break; +        } + +        if (i == len) { +                gf_log ("common-utils", GF_LOG_ERROR, "Hard limit not found"); +                return -1; +        } + +        hlbegin = i + 1; +        i++; + +        while ((limit[i] != '\0') && (limit[i] != ':')) { +                i++; +        } + +        hl = GF_CALLOC (i - hlbegin + 1, sizeof (char), gf_common_mt_char); +        if (!hl) +                return -1; + +        strncpy (hl, &limit[hlbegin], i - hlbegin); +        *hard_limit = hl; + +        return 0; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index e762a86eaf4..acf2202d54e 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -81,6 +81,11 @@ void trap (void);  #define GF_NFS3_PORT    2049  #define GF_CLIENT_PORT_CEILING 1024 +#define GF_MINUTE_IN_SECONDS 60 +#define GF_HOUR_IN_SECONDS (60*60) +#define GF_DAY_IN_SECONDS (24*60*60) +#define GF_WEEK_IN_SECONDS (7*24*60*60) +  enum _gf_boolean  {  	_gf_false = 0, @@ -176,6 +181,18 @@ int  gf_set_log_file_path (cmd_args_t *cmd_args);                  }                                                       \          } while (0) +#define GF_REMOVE_INTERNAL_XATTR(pattern, dict)                         \ +        do {                                                            \ +                if (!dict) {                                            \ +                        gf_log (this->name, GF_LOG_ERROR,               \ +                                "dict is null");                        \ +                        break;                                          \ +                }                                                       \ +                dict_foreach_fnmatch (dict, pattern,                    \ +                                      dict_remove_foreach_fn,           \ +                                      NULL);                            \ +        } while (0) +  #define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label)       \          do {                                                            \                  if (!dict) {                                            \ @@ -595,4 +612,7 @@ size_t backtrace(void **, size_t);  char **backtrace_symbols(void *const *, size_t);  #endif +int gf_get_soft_limit (char *limit, char **soft_limit); +int gf_get_hard_limit (char *limit, char **hard_limit); +  #endif /* _COMMON_UTILS_H */ diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index 3b7ddce5e0d..f2df5a6d431 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -1086,6 +1086,20 @@ dict_null_foreach_fn (dict_t *d, char *k,  }  int +dict_remove_foreach_fn (dict_t *d, char *k, +                        data_t *v, void *_tmp) +{ +        if (!d || !k) { +                gf_log ("glusterfs", GF_LOG_WARNING, "%s is NULL", +                        d?"key":"dictionary"); +                return -1; +        } + +        dict_del (d, k); +        return 0; +} + +int  dict_foreach (dict_t *dict,                int (*fn)(dict_t *this,                          char *key, diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 9b41b5a7df0..6e5d8aa0650 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -179,7 +179,8 @@ int dict_foreach_fnmatch (dict_t *dict, char *pattern,  int dict_null_foreach_fn (dict_t *d, char *k,                            data_t *v, void *tmp); - +int dict_remove_foreach_fn (dict_t *d, char *k, +                            data_t *v, void *tmp);  dict_t *dict_copy (dict_t *this, dict_t *new);  int dict_keys_join (void *value, int size, dict_t *dict,                      int (*filter_fn)(char *key)); diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 525d6909a59..8f05a222d58 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -85,6 +85,7 @@  #define GF_XATTR_VOL_ID_KEY   "trusted.glusterfs.volume-id"  #define GF_XATTR_LOCKINFO_KEY   "trusted.glusterfs.lockinfo"  #define GF_XATTR_GET_REAL_FILENAME_KEY "user.glusterfs.get_real_filename:" +#define QUOTA_LIMIT_KEY "trusted.glusterfs.quota.limit-set"  #define GF_READDIR_SKIP_DIRS       "readdir-filter-directories" diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index a8897626545..60adba68425 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -142,6 +142,9 @@ inode_rename (inode_table_t *table, inode_t *olddir, const char *oldname,  	      inode_t *newdir, const char *newname,  	      inode_t *inode, struct iatt *stbuf); +dentry_t * +__dentry_grep (inode_table_t *table, inode_t *parent, const char *name); +  inode_t *  inode_grep (inode_table_t *table, inode_t *parent, const char *name); diff --git a/libglusterfs/src/options.c b/libglusterfs/src/options.c index 842b6413ab4..31e5a681d11 100644 --- a/libglusterfs/src/options.c +++ b/libglusterfs/src/options.c @@ -1110,7 +1110,7 @@ DEFINE_INIT_OPT(gf_boolean_t, bool, gf_string2boolean);  DEFINE_INIT_OPT(xlator_t *, xlator, xl_by_name);  DEFINE_INIT_OPT(char *, path, pass);  DEFINE_INIT_OPT(double, double, gf_string2double); - +DEFINE_INIT_OPT(uint32_t, time, gf_string2time);  DEFINE_RECONF_OPT(char *, str, pass); @@ -1125,3 +1125,4 @@ DEFINE_RECONF_OPT(gf_boolean_t, bool, gf_string2boolean);  DEFINE_RECONF_OPT(xlator_t *, xlator, xl_by_name);  DEFINE_RECONF_OPT(char *, path, pass);  DEFINE_RECONF_OPT(double, double, gf_string2double); +DEFINE_RECONF_OPT(uint32_t, time, gf_string2time); diff --git a/libglusterfs/src/options.h b/libglusterfs/src/options.h index e2a25baa9e7..62f4ee92e91 100644 --- a/libglusterfs/src/options.h +++ b/libglusterfs/src/options.h @@ -114,6 +114,7 @@ DECLARE_INIT_OPT(gf_boolean_t, bool);  DECLARE_INIT_OPT(xlator_t *, xlator);  DECLARE_INIT_OPT(char *, path);  DECLARE_INIT_OPT(double, double); +DECLARE_INIT_OPT(uint32_t, time);  #define DEFINE_INIT_OPT(type_t, type, conv)                             \ @@ -194,6 +195,7 @@ DECLARE_RECONF_OPT(gf_boolean_t, bool);  DECLARE_RECONF_OPT(xlator_t *, xlator);  DECLARE_RECONF_OPT(char *, path);  DECLARE_RECONF_OPT(double, double); +DECLARE_RECONF_OPT(uint32_t, time);  #define DEFINE_RECONF_OPT(type_t, type, conv)                            \ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index a277c58a8f5..7c8c3cdba36 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -659,7 +659,6 @@ loc_copy (loc_t *dst, loc_t *src)          uuid_copy (dst->gfid, src->gfid);          uuid_copy (dst->pargfid, src->pargfid); -        uuid_copy (dst->gfid, src->gfid);          if (src->inode)                  dst->inode = inode_ref (src->inode);  | 
