All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Simmons <jsimmons@infradead.org>
To: lustre-devel@lists.lustre.org
Subject: [lustre-devel] [PATCH 16/22] ext4: add warning for directory htree growth
Date: Sun, 21 Jul 2019 21:23:45 -0400	[thread overview]
Message-ID: <1563758631-29550-17-git-send-email-jsimmons@infradead.org> (raw)
In-Reply-To: <1563758631-29550-1-git-send-email-jsimmons@infradead.org>

Signed-off-by: James Simmons <jsimmons@infradead.org>
---
 fs/ext4/ext4.h  |  1 +
 fs/ext4/namei.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 fs/ext4/super.c |  2 ++
 fs/ext4/sysfs.c |  2 ++
 4 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index bf74c7c..5f73e19 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1472,6 +1472,7 @@ struct ext4_sb_info {
 	unsigned int s_mb_group_prealloc;
 	unsigned long *s_mb_prealloc_table;
 	unsigned int s_max_dir_size_kb;
+	unsigned long s_warning_dir_size;
 	/* where last allocation was done - for stream allocation */
 	unsigned long s_mb_last_group;
 	unsigned long s_mb_last_start;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1b6d22a..9b30cc6 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -757,12 +757,20 @@ struct ext4_dir_lock_data {
 #define ext4_htree_lock_data(l)	((struct ext4_dir_lock_data *)(l)->lk_private)
 #define ext4_find_entry(dir, name, dirent, inline) \
 			ext4_find_entry_locked(dir, name, dirent, inline, NULL)
-#define ext4_add_entry(handle, dentry, inode) \
-		       ext4_add_entry_locked(handle, dentry, inode, NULL)
 
 /* NB: ext4_lblk_t is 32 bits so we use high bits to identify invalid blk */
 #define EXT4_HTREE_NODE_CHANGED		(0xcafeULL << 32)
 
+inline int ext4_add_entry(handle_t *handle, struct dentry *dentry,
+			  struct inode *inode)
+{
+	int ret = ext4_add_entry_locked(handle, dentry, inode, NULL);
+
+	if (ret == -ENOBUFS)
+		ret = 0;
+	return ret;
+}
+
 static void ext4_htree_event_cb(void *target, void *event)
 {
 	u64 *block = (u64 *)target;
@@ -2612,6 +2620,55 @@ static int ext4_update_dotdot(handle_t *handle, struct dentry *dentry,
 	return err;
 }
 
+static unsigned long __ext4_max_dir_size(struct dx_frame *frames,
+					 struct dx_frame *frame,
+					 struct inode *dir)
+{
+	unsigned long max_dir_size;
+
+	if (EXT4_SB(dir->i_sb)->s_max_dir_size_kb) {
+		max_dir_size = EXT4_SB(dir->i_sb)->s_max_dir_size_kb << 10;
+	} else {
+		max_dir_size = EXT4_BLOCK_SIZE(dir->i_sb);
+		while (frame >= frames) {
+			max_dir_size *= dx_get_limit(frame->entries);
+			if (frame == frames)
+				break;
+			frame--;
+		}
+		/* use 75% of max dir size in average */
+		max_dir_size = max_dir_size / 4 * 3;
+	}
+	return max_dir_size;
+}
+
+/*
+ * With hash tree growing, it is easy to hit ENOSPC, but it is hard
+ * to predict when it will happen. let's give administrators warning
+ * when reaching 3/5 and 2/3 of limit
+ */
+static inline bool dir_size_in_warning_range(struct dx_frame *frames,
+					     struct dx_frame *frame,
+					     struct inode *dir)
+{
+	struct super_block *sb = dir->i_sb;
+	unsigned long size1, size2;
+
+	if (unlikely(!EXT4_SB(sb)->s_warning_dir_size))
+		EXT4_SB(sb)->s_warning_dir_size =
+			__ext4_max_dir_size(frames, frame, dir);
+
+	size1 = EXT4_SB(sb)->s_warning_dir_size / 16 * 10;
+	size1 = size1 & ~(EXT4_BLOCK_SIZE(sb) - 1);
+	size2 = EXT4_SB(sb)->s_warning_dir_size / 16 * 11;
+	size2 = size2 & ~(EXT4_BLOCK_SIZE(sb) - 1);
+	if (in_range(dir->i_size, size1, EXT4_BLOCK_SIZE(sb)) ||
+	    in_range(dir->i_size, size2, EXT4_BLOCK_SIZE(sb)))
+		return true;
+
+	return false;
+}
+
 /*
  *	ext4_add_entry()
  *
@@ -2739,6 +2796,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
 	struct buffer_head *bh;
 	struct super_block *sb = dir->i_sb;
 	struct ext4_dir_entry_2 *de;
+	bool ret_warn = false;
 	int restart;
 	int err;
 
@@ -2769,6 +2827,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
 	/* Block full, should compress but for now just split */
 	dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
 		       dx_get_count(entries), dx_get_limit(entries)));
+
+	if (frame - frames + 1 >= ext4_dir_htree_level(sb) ||
+	    EXT4_SB(sb)->s_warning_dir_size)
+		ret_warn = dir_size_in_warning_range(frames, frame, dir);
+
 	/* Need to split index? */
 	if (dx_get_count(entries) == dx_get_limit(entries)) {
 		ext4_lblk_t newblock;
@@ -2935,6 +2998,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
 	 */
 	if (restart && err == 0)
 		goto again;
+	if (err == 0 && ret_warn)
+		err = -ENOBUFS;
 	return err;
 }
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 07242d7..a3179b2 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1901,6 +1901,8 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
 		sbi->s_li_wait_mult = arg;
 	} else if (token == Opt_max_dir_size_kb) {
 		sbi->s_max_dir_size_kb = arg;
+		/* reset s_warning_dir_size and make it re-calculated */
+		sbi->s_warning_dir_size = 0;
 	} else if (token == Opt_stripe) {
 		sbi->s_stripe = arg;
 	} else if (token == Opt_resuid) {
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 3a71a16..575f318 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -182,6 +182,7 @@ static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf)
 EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
 EXT4_RW_ATTR_SBI_UI(max_dir_size, s_max_dir_size_kb);
 EXT4_RW_ATTR_SBI_UI(max_dir_size_kb, s_max_dir_size_kb);
+EXT4_RW_ATTR_SBI_UI(warning_dir_size, s_warning_dir_size);
 EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
 EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
 EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
@@ -214,6 +215,7 @@ static ssize_t journal_task_show(struct ext4_sb_info *sbi, char *buf)
 	ATTR_LIST(inode_goal),
 	ATTR_LIST(max_dir_size),
 	ATTR_LIST(max_dir_size_kb),
+	ATTR_LIST(warning_dir_size),
 	ATTR_LIST(mb_stats),
 	ATTR_LIST(mb_max_to_scan),
 	ATTR_LIST(mb_min_to_scan),
-- 
1.8.3.1

  parent reply	other threads:[~2019-07-22  1:23 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-22  1:23 [lustre-devel] [PATCH 00/22] [RFC] ldiskfs patches against 5.2-rc2+ James Simmons
2019-07-22  1:23 ` [lustre-devel] [PATCH 01/22] ext4: add i_fs_version James Simmons
2019-07-22  4:13   ` NeilBrown
2019-07-23  0:07     ` James Simmons
2019-07-31 22:03     ` Andreas Dilger
2019-07-22  1:23 ` [lustre-devel] [PATCH 02/22] ext4: use d_find_alias() in ext4_lookup James Simmons
2019-07-22  4:16   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 03/22] ext4: prealloc table optimization James Simmons
2019-07-22  4:29   ` NeilBrown
2019-08-05  7:07   ` Artem Blagodarenko
2019-07-22  1:23 ` [lustre-devel] [PATCH 04/22] ext4: export inode management James Simmons
2019-07-22  4:34   ` NeilBrown
2019-07-22  7:16     ` Oleg Drokin
2019-07-22  1:23 ` [lustre-devel] [PATCH 05/22] ext4: various misc changes James Simmons
2019-07-22  1:23 ` [lustre-devel] [PATCH 06/22] ext4: add extra checks for mballoc James Simmons
2019-07-22  4:37   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 07/22] ext4: update .. for hash indexed directory James Simmons
2019-07-22  4:45   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 08/22] ext4: kill off struct dx_root James Simmons
2019-07-22  4:52   ` NeilBrown
2019-07-23  2:07     ` Andreas Dilger
2019-08-05  7:31     ` Artem Blagodarenko
2019-07-22  1:23 ` [lustre-devel] [PATCH 09/22] ext4: fix mballoc pa free mismatch James Simmons
2019-07-22  4:56   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 10/22] ext4: add data in dentry feature James Simmons
2019-07-22  1:23 ` [lustre-devel] [PATCH 11/22] ext4: over ride current_time James Simmons
2019-07-22  5:06   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 12/22] ext4: add htree lock implementation James Simmons
2019-07-22  5:10   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 13/22] ext4: Add a proc interface for max_dir_size James Simmons
2019-07-22  5:14   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 14/22] ext4: remove inode_lock handling James Simmons
2019-07-22  5:16   ` NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 15/22] ext4: remove bitmap corruption warnings James Simmons
2019-07-22  5:18   ` NeilBrown
2019-07-22  1:23 ` James Simmons [this message]
2019-07-22  5:24   ` [lustre-devel] [PATCH 16/22] ext4: add warning for directory htree growth NeilBrown
2019-07-22  1:23 ` [lustre-devel] [PATCH 17/22] ext4: optimize ext4_journal_callback_add James Simmons
2019-07-22  5:27   ` NeilBrown
2019-07-23  2:01     ` Andreas Dilger
2019-07-22  1:23 ` [lustre-devel] [PATCH 18/22] ext4: attach jinode in writepages James Simmons
2019-07-22  1:23 ` [lustre-devel] [PATCH 19/22] ext4: don't check before replay James Simmons
2019-07-22  5:29   ` NeilBrown
     [not found]     ` <506765DD-0068-469E-ADA4-2C71B8B60114@cloudlinux.com>
2019-07-22  6:46       ` NeilBrown
2019-07-22  6:56         ` Oleg Drokin
2019-07-22  9:51           ` Alexey Lyashkov
2019-07-23  1:57     ` Andreas Dilger
2019-07-23  2:01       ` Oleg Drokin
2019-07-22  1:23 ` [lustre-devel] [PATCH 20/22] ext4: use GFP_NOFS in ext4_inode_attach_jinode James Simmons
2019-07-22  5:30   ` NeilBrown
2019-07-23  1:56     ` Andreas Dilger
2019-07-22  1:23 ` [lustre-devel] [PATCH 21/22] ext4: export ext4_orphan_add James Simmons
2019-07-22  1:23 ` [lustre-devel] [PATCH 22/22] ext4: export mb stream allocator variables James Simmons

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1563758631-29550-17-git-send-email-jsimmons@infradead.org \
    --to=jsimmons@infradead.org \
    --cc=lustre-devel@lists.lustre.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.