From 5a29779aceec59069511cec7eff9b314e819eacc Mon Sep 17 00:00:00 2001 From: Shreyas Siravara Date: Thu, 7 Sep 2017 16:36:29 -0700 Subject: storage/posix: Add limit to number of hard links Summary: Too may hard links blow up btrfs by exceeding max xattr size (recordign pgfid for each hardlink). Add a limit to prevent this explosion. > Reviewed-on: https://review.gluster.org/18232 > Reviewed-by: Shreyas Siravara Fixes gluster/glusterfs#370 Signed-off-by: ShyamsundarR Change-Id: I614a247834fb8f2b2743c0c67d11cefafff0dbaa --- xlators/mgmt/glusterd/src/glusterd-volume-set.c | 5 +++++ xlators/storage/posix/src/posix-common.c | 16 ++++++++++++++++ xlators/storage/posix/src/posix-entry-ops.c | 9 +++++++++ xlators/storage/posix/src/posix.h | 1 + 4 files changed, 31 insertions(+) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 7750914705e..eef95e8809d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -2843,6 +2843,11 @@ struct volopt_map_entry glusterd_volopt_map[] = { .voltype = "storage/posix", .op_version = GD_OP_VERSION_4_0_0, }, + { .option = "max-hardlinks", + .key = "storage.max-hardlinks", + .voltype = "storage/posix", + .op_version = GD_OP_VERSION_4_0_0, + }, { .key = "storage.bd-aio", .voltype = "storage/bd", .op_version = 3 diff --git a/xlators/storage/posix/src/posix-common.c b/xlators/storage/posix/src/posix-common.c index 011bef8a720..1b2bb609fb0 100644 --- a/xlators/storage/posix/src/posix-common.c +++ b/xlators/storage/posix/src/posix-common.c @@ -398,6 +398,8 @@ posix_reconfigure (xlator_t *this, dict_t *options) options, int32, out); priv->create_directory_mask = create_directory_mask; + GF_OPTION_RECONF ("max-hardlinks", priv->max_hardlinks, + options, uint32, out); ret = 0; out: return ret; @@ -1075,6 +1077,8 @@ posix_init (xlator_t *this) GF_OPTION_INIT ("create-directory-mask", create_directory_mask, int32, out); _private->create_directory_mask = create_directory_mask; + + GF_OPTION_INIT ("max-hardlinks", _private->max_hardlinks, uint32, out); out: if (ret) { if (_private) { @@ -1322,5 +1326,17 @@ struct volume_options options[] = { .description = "Any bit not set here will be removed from the" "modes set on a directory when it is created" }, + { + .key = {"max-hardlinks"}, + .type = GF_OPTION_TYPE_INT, + .min = 0, + .default_value = "100", + .op_version = {GD_OP_VERSION_4_0_0}, + .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC, + .tags = {"posix"}, + .validate = GF_OPT_VALIDATE_MIN, + .description = "max number of hardlinks allowed on any one inode.\n" + "0 is unlimited, 1 prevents any hardlinking at all." + }, { .key = {NULL} } }; diff --git a/xlators/storage/posix/src/posix-entry-ops.c b/xlators/storage/posix/src/posix-entry-ops.c index 7a83eb3dfba..e7658e46543 100644 --- a/xlators/storage/posix/src/posix-entry-ops.c +++ b/xlators/storage/posix/src/posix-entry-ops.c @@ -1814,6 +1814,15 @@ posix_link (call_frame_t *frame, xlator_t *this, goto out; } + if (priv->max_hardlinks && stbuf.ia_nlink >= priv->max_hardlinks) { + op_ret = -1; + op_errno = EMLINK; + gf_log (this->name, GF_LOG_ERROR, + "hardlink failed: %s exceeds max link count (%u/%u).", + real_oldpath, stbuf.ia_nlink, priv->max_hardlinks); + goto out; + } + MAKE_ENTRY_HANDLE (real_newpath, par_newpath, this, newloc, &stbuf); if (!real_newpath || !par_newpath) { op_ret = -1; diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index 36348767870..afb4b4413f6 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -239,6 +239,7 @@ struct posix_private { mode_t force_directory_mode; mode_t create_mask; mode_t create_directory_mask; + uint32_t max_hardlinks; }; typedef struct { -- cgit