* [PATCH 0/6] Btrfs send updates - reduce memory consumption
@ 2014-02-03 18:21 David Sterba
2014-02-03 18:23 ` [PATCH 1/6] btrfs: send: remove prepared member from fs_path David Sterba
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:21 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
[Sorry if you see this twice, first attempt hasn't appeared in the list yet]
This reduces size of the path buffer in common case. Has been tested by
xfstests, but at the moment v3.13 with or without this patch blows, so I'm
sending it anyway.
Based on current btrfs-next/master.
David Sterba (6):
btrfs: send: remove prepared member from fs_path
btrfs: send: remove virtual_mem member from fs_path
btrfs: send: squeeze bitfilelds in fs_path
btrfs: send: lower memory requirements in common case
btrfs: send: remove BUG from process_all_refs
btrfs: send: remove BUG_ON from name_cache_delete
fs/btrfs/send.c | 153 ++++++++++++++++++++++--------------------------------
1 files changed, 62 insertions(+), 91 deletions(-)
--
1.7.9
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/6] btrfs: send: remove prepared member from fs_path
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
@ 2014-02-03 18:23 ` David Sterba
2014-02-03 18:23 ` [PATCH 2/6] btrfs: send: remove virtual_mem " David Sterba
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:23 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
The member is used only to return value back from
fs_path_prepare_for_add, we can do it locally and save 8 bytes for the
inline_buf path.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 04c07ed51df5..524086a882f9 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -51,7 +51,6 @@ struct fs_path {
struct {
char *start;
char *end;
- char *prepared;
char *buf;
int buf_len;
@@ -338,7 +337,8 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
return 0;
}
-static int fs_path_prepare_for_add(struct fs_path *p, int name_len)
+static int fs_path_prepare_for_add(struct fs_path *p, int name_len,
+ char **prepared)
{
int ret;
int new_len;
@@ -354,11 +354,11 @@ static int fs_path_prepare_for_add(struct fs_path *p, int name_len)
if (p->start != p->end)
*--p->start = '/';
p->start -= name_len;
- p->prepared = p->start;
+ *prepared = p->start;
} else {
if (p->start != p->end)
*p->end++ = '/';
- p->prepared = p->end;
+ *prepared = p->end;
p->end += name_len;
*p->end = 0;
}
@@ -370,12 +370,12 @@ out:
static int fs_path_add(struct fs_path *p, const char *name, int name_len)
{
int ret;
+ char *prepared;
- ret = fs_path_prepare_for_add(p, name_len);
+ ret = fs_path_prepare_for_add(p, name_len, &prepared);
if (ret < 0)
goto out;
- memcpy(p->prepared, name, name_len);
- p->prepared = NULL;
+ memcpy(prepared, name, name_len);
out:
return ret;
@@ -384,12 +384,12 @@ out:
static int fs_path_add_path(struct fs_path *p, struct fs_path *p2)
{
int ret;
+ char *prepared;
- ret = fs_path_prepare_for_add(p, p2->end - p2->start);
+ ret = fs_path_prepare_for_add(p, p2->end - p2->start, &prepared);
if (ret < 0)
goto out;
- memcpy(p->prepared, p2->start, p2->end - p2->start);
- p->prepared = NULL;
+ memcpy(prepared, p2->start, p2->end - p2->start);
out:
return ret;
@@ -400,13 +400,13 @@ static int fs_path_add_from_extent_buffer(struct fs_path *p,
unsigned long off, int len)
{
int ret;
+ char *prepared;
- ret = fs_path_prepare_for_add(p, len);
+ ret = fs_path_prepare_for_add(p, len, &prepared);
if (ret < 0)
goto out;
- read_extent_buffer(eb, p->prepared, off, len);
- p->prepared = NULL;
+ read_extent_buffer(eb, prepared, off, len);
out:
return ret;
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/6] btrfs: send: remove virtual_mem member from fs_path
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
2014-02-03 18:23 ` [PATCH 1/6] btrfs: send: remove prepared member from fs_path David Sterba
@ 2014-02-03 18:23 ` David Sterba
2014-02-03 18:23 ` [PATCH 3/6] btrfs: send: squeeze bitfilelds in fs_path David Sterba
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:23 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
We don't need to keep track of that, it's available via is_vmalloc_addr.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 524086a882f9..ea427624e842 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -55,7 +55,6 @@ struct fs_path {
char *buf;
int buf_len;
unsigned int reversed:1;
- unsigned int virtual_mem:1;
char inline_buf[];
};
char pad[PAGE_SIZE];
@@ -241,7 +240,6 @@ static struct fs_path *fs_path_alloc(void)
if (!p)
return NULL;
p->reversed = 0;
- p->virtual_mem = 0;
p->buf = p->inline_buf;
p->buf_len = FS_PATH_INLINE_SIZE;
fs_path_reset(p);
@@ -265,7 +263,7 @@ static void fs_path_free(struct fs_path *p)
if (!p)
return;
if (p->buf != p->inline_buf) {
- if (p->virtual_mem)
+ if (is_vmalloc_addr(p->buf))
vfree(p->buf);
else
kfree(p->buf);
@@ -299,13 +297,12 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
tmp_buf = vmalloc(len);
if (!tmp_buf)
return -ENOMEM;
- p->virtual_mem = 1;
}
memcpy(tmp_buf, p->buf, p->buf_len);
p->buf = tmp_buf;
p->buf_len = len;
} else {
- if (p->virtual_mem) {
+ if (is_vmalloc_addr(p->buf)) {
tmp_buf = vmalloc(len);
if (!tmp_buf)
return -ENOMEM;
@@ -319,7 +316,6 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
return -ENOMEM;
memcpy(tmp_buf, p->buf, p->buf_len);
kfree(p->buf);
- p->virtual_mem = 1;
}
}
p->buf = tmp_buf;
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/6] btrfs: send: squeeze bitfilelds in fs_path
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
2014-02-03 18:23 ` [PATCH 1/6] btrfs: send: remove prepared member from fs_path David Sterba
2014-02-03 18:23 ` [PATCH 2/6] btrfs: send: remove virtual_mem " David Sterba
@ 2014-02-03 18:23 ` David Sterba
2014-02-03 18:23 ` [PATCH 4/6] btrfs: send: lower memory requirements in common case David Sterba
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:23 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
We know that buf_len is at most PATH_MAX, 4k, and can merge it with the
reversed member. This saves 3 bytes in favor of inline_buf.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index ea427624e842..cb12c2ec37dc 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -53,8 +53,8 @@ struct fs_path {
char *end;
char *buf;
- int buf_len;
- unsigned int reversed:1;
+ unsigned short buf_len:15;
+ unsigned short reversed:1;
char inline_buf[];
};
char pad[PAGE_SIZE];
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/6] btrfs: send: lower memory requirements in common case
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
` (2 preceding siblings ...)
2014-02-03 18:23 ` [PATCH 3/6] btrfs: send: squeeze bitfilelds in fs_path David Sterba
@ 2014-02-03 18:23 ` David Sterba
2014-02-03 18:24 ` [PATCH 5/6] btrfs: send: remove BUG from process_all_refs David Sterba
2014-02-03 18:24 ` [PATCH 6/6] btrfs: send: remove BUG_ON from name_cache_delete David Sterba
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:23 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
The fs_path structure uses an inline buffer and falls back to a chain of
allocations, but vmalloc is not necessary because PATH_MAX fits into
PAGE_SIZE.
The size of fs_path has been reduced to 256 bytes from PAGE_SIZE,
usually 4k. Experimental measurements show that most paths on a single
filesystem do not exceed 200 bytes, and these get stored into the inline
buffer directly, which is now 230 bytes. Longer paths are kmalloced when
needed.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 103 ++++++++++++++++++-------------------------------------
1 files changed, 34 insertions(+), 69 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index cb12c2ec37dc..4e3a3d413417 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -57,7 +57,12 @@ struct fs_path {
unsigned short reversed:1;
char inline_buf[];
};
- char pad[PAGE_SIZE];
+ /*
+ * Average path length does not exceed 200 bytes, we'll have
+ * better packing in the slab and higher chance to satisfy
+ * a allocation later during send.
+ */
+ char pad[256];
};
};
#define FS_PATH_INLINE_SIZE \
@@ -262,12 +267,8 @@ static void fs_path_free(struct fs_path *p)
{
if (!p)
return;
- if (p->buf != p->inline_buf) {
- if (is_vmalloc_addr(p->buf))
- vfree(p->buf);
- else
- kfree(p->buf);
- }
+ if (p->buf != p->inline_buf)
+ kfree(p->buf);
kfree(p);
}
@@ -287,40 +288,28 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
if (p->buf_len >= len)
return 0;
- path_len = p->end - p->start;
- old_buf_len = p->buf_len;
- len = PAGE_ALIGN(len);
-
+ /*
+ * First time the inline_buf does not suffice
+ */
if (p->buf == p->inline_buf) {
- tmp_buf = kmalloc(len, GFP_NOFS | __GFP_NOWARN);
- if (!tmp_buf) {
- tmp_buf = vmalloc(len);
- if (!tmp_buf)
- return -ENOMEM;
- }
- memcpy(tmp_buf, p->buf, p->buf_len);
- p->buf = tmp_buf;
- p->buf_len = len;
+ p->buf = kmalloc(len, GFP_NOFS);
+ if (!p->buf)
+ return -ENOMEM;
+ /*
+ * The real size of the buffer is bigger, this will let the
+ * fast path happen most of the time
+ */
+ p->buf_len = ksize(p->buf);
} else {
- if (is_vmalloc_addr(p->buf)) {
- tmp_buf = vmalloc(len);
- if (!tmp_buf)
- return -ENOMEM;
- memcpy(tmp_buf, p->buf, p->buf_len);
- vfree(p->buf);
- } else {
- tmp_buf = krealloc(p->buf, len, GFP_NOFS);
- if (!tmp_buf) {
- tmp_buf = vmalloc(len);
- if (!tmp_buf)
- return -ENOMEM;
- memcpy(tmp_buf, p->buf, p->buf_len);
- kfree(p->buf);
- }
- }
- p->buf = tmp_buf;
- p->buf_len = len;
+ p->buf = krealloc(p->buf, len, GFP_NOFS);
+ if (!p->buf)
+ return -ENOMEM;
+ p->buf_len = ksize(p->buf);
}
+
+ path_len = p->end - p->start;
+ old_buf_len = p->buf_len;
+
if (p->reversed) {
tmp_buf = p->buf + old_buf_len - path_len - 1;
p->end = p->buf + p->buf_len - 1;
@@ -911,9 +900,7 @@ static int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path,
struct btrfs_dir_item *di;
struct btrfs_key di_key;
char *buf = NULL;
- char *buf2 = NULL;
- int buf_len;
- int buf_virtual = 0;
+ const int buf_len = PATH_MAX;
u32 name_len;
u32 data_len;
u32 cur;
@@ -923,7 +910,6 @@ static int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path,
int num;
u8 type;
- buf_len = PAGE_SIZE;
buf = kmalloc(buf_len, GFP_NOFS);
if (!buf) {
ret = -ENOMEM;
@@ -945,30 +931,12 @@ static int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path,
type = btrfs_dir_type(eb, di);
btrfs_dir_item_key_to_cpu(eb, di, &di_key);
+ /*
+ * Path too long
+ */
if (name_len + data_len > buf_len) {
- buf_len = PAGE_ALIGN(name_len + data_len);
- if (buf_virtual) {
- buf2 = vmalloc(buf_len);
- if (!buf2) {
- ret = -ENOMEM;
- goto out;
- }
- vfree(buf);
- } else {
- buf2 = krealloc(buf, buf_len, GFP_NOFS);
- if (!buf2) {
- buf2 = vmalloc(buf_len);
- if (!buf2) {
- ret = -ENOMEM;
- goto out;
- }
- kfree(buf);
- buf_virtual = 1;
- }
- }
-
- buf = buf2;
- buf2 = NULL;
+ ret = -ENAMETOOLONG;
+ goto out;
}
read_extent_buffer(eb, buf, (unsigned long)(di + 1),
@@ -991,10 +959,7 @@ static int iterate_dir_item(struct btrfs_root *root, struct btrfs_path *path,
}
out:
- if (buf_virtual)
- vfree(buf);
- else
- kfree(buf);
+ kfree(buf);
return ret;
}
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/6] btrfs: send: remove BUG from process_all_refs
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
` (3 preceding siblings ...)
2014-02-03 18:23 ` [PATCH 4/6] btrfs: send: lower memory requirements in common case David Sterba
@ 2014-02-03 18:24 ` David Sterba
2014-02-03 18:24 ` [PATCH 6/6] btrfs: send: remove BUG_ON from name_cache_delete David Sterba
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:24 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
There are only 2 static callers, the BUG would normally be never
reached, but let's be nice.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 4e3a3d413417..b0bf4ff40b5b 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3568,7 +3568,10 @@ static int process_all_refs(struct send_ctx *sctx,
root = sctx->parent_root;
cb = __record_deleted_ref;
} else {
- BUG();
+ btrfs_err(sctx->send_root->fs_info,
+ "Wrong command %d in process_all_refs", cmd);
+ ret = -EINVAL;
+ goto out;
}
key.objectid = sctx->cmp_key->objectid;
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/6] btrfs: send: remove BUG_ON from name_cache_delete
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
` (4 preceding siblings ...)
2014-02-03 18:24 ` [PATCH 5/6] btrfs: send: remove BUG from process_all_refs David Sterba
@ 2014-02-03 18:24 ` David Sterba
5 siblings, 0 replies; 7+ messages in thread
From: David Sterba @ 2014-02-03 18:24 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
If cleaning the name cache fails, we could try to proceed at the cost of
some memory leak. This is not expected to happen often.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/send.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index b0bf4ff40b5b..7b17b778eaf7 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1849,13 +1849,20 @@ static void name_cache_delete(struct send_ctx *sctx,
nce_head = radix_tree_lookup(&sctx->name_cache,
(unsigned long)nce->ino);
- BUG_ON(!nce_head);
+ if (!nce_head) {
+ btrfs_err(sctx->send_root->fs_info,
+ "name_cache_delete lookup failed ino %llu cache size %d, leaking memory",
+ nce->ino, sctx->name_cache_size);
+ }
list_del(&nce->radix_list);
list_del(&nce->list);
sctx->name_cache_size--;
- if (list_empty(nce_head)) {
+ /*
+ * We may not get to the final release of nce_head if the lookup fails
+ */
+ if (nce_head && list_empty(nce_head)) {
radix_tree_delete(&sctx->name_cache, (unsigned long)nce->ino);
kfree(nce_head);
}
--
1.7.9
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-02-03 18:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-03 18:21 [PATCH 0/6] Btrfs send updates - reduce memory consumption David Sterba
2014-02-03 18:23 ` [PATCH 1/6] btrfs: send: remove prepared member from fs_path David Sterba
2014-02-03 18:23 ` [PATCH 2/6] btrfs: send: remove virtual_mem " David Sterba
2014-02-03 18:23 ` [PATCH 3/6] btrfs: send: squeeze bitfilelds in fs_path David Sterba
2014-02-03 18:23 ` [PATCH 4/6] btrfs: send: lower memory requirements in common case David Sterba
2014-02-03 18:24 ` [PATCH 5/6] btrfs: send: remove BUG from process_all_refs David Sterba
2014-02-03 18:24 ` [PATCH 6/6] btrfs: send: remove BUG_ON from name_cache_delete David Sterba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).