* [PATCH 0/2] Add perf debug dir locking
@ 2015-05-14 7:28 Milos Vyletel
2015-05-14 7:28 ` [PATCH 1/2] perf/tools: add read/write buildid dir locks Milos Vyletel
2015-05-14 7:28 ` [PATCH 2/2] perf/tools: put new buildid locks to use Milos Vyletel
0 siblings, 2 replies; 12+ messages in thread
From: Milos Vyletel @ 2015-05-14 7:28 UTC (permalink / raw)
To: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Milos Vyletel, Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
Hi,
this series is follow up on my last submission where Jirka mentioned it would
be nice to have some locking around .debug dir operations.
https://lkml.org/lkml/2015/3/20/126
Following two patches add such functionality by utilizing flock. Since flock
supports both shared(read) and exclusive(write) locks both variants are being
added so that we can use multiple readers while only one writer.
Having said that any comments/suggestions on the code are welcome.
I did some basic testing. Mostly manual tool testing as well as the recreator
from above mentioned URL. I do not expect any functional change however more
testing is welcome.
Milos
Milos Vyletel (2):
perf/tools: add read/write buildid dir locks
perf/tools: put new buildid locks to use
tools/perf/builtin-buildid-cache.c | 12 +++++
tools/perf/util/build-id.c | 97 ++++++++++++++++++++++++++++++++++----
tools/perf/util/build-id.h | 5 ++
3 files changed, 106 insertions(+), 8 deletions(-)
--
2.4.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] perf/tools: add read/write buildid dir locks
2015-05-14 7:28 [PATCH 0/2] Add perf debug dir locking Milos Vyletel
@ 2015-05-14 7:28 ` Milos Vyletel
2015-05-14 7:28 ` [PATCH 2/2] perf/tools: put new buildid locks to use Milos Vyletel
1 sibling, 0 replies; 12+ messages in thread
From: Milos Vyletel @ 2015-05-14 7:28 UTC (permalink / raw)
To: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Milos Vyletel, Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
Protect access to buildid dir by flock to prevent race conditions. This
patch adds buildid_dir_read/write_lock/unlock functions.
Signed-off-by: Milos Vyletel <milos@redhat.com>
---
tools/perf/util/build-id.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/build-id.h | 5 +++++
2 files changed, 61 insertions(+)
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 61867df..46c41e1 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -536,3 +536,59 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
return ret;
}
+
+static int buildid_dir_lock(int op)
+{
+ int lockfd, wait = 30;
+ const size_t size = PATH_MAX;
+ char *lockfile = zalloc(size);
+
+ scnprintf(lockfile, size, "%s/.lock", buildid_dir);
+
+ lockfd = open(lockfile, O_RDONLY|O_CREAT, S_IRUSR);
+ if (lockfd == -1)
+ goto out;
+
+ while (1) {
+ if (flock(lockfd, op | LOCK_NB) == 0)
+ goto out;
+ else if (wait == 0) {
+ close(lockfd);
+ lockfd = -1;
+ goto out;
+ }
+ if (--wait % 10 == 0)
+ pr_info("Waiting for %s lock to be available\n", buildid_dir);
+ usleep(100);
+ }
+
+out:
+ free(lockfile);
+ return lockfd;
+}
+
+static void buildid_dir_unlock(int fd)
+{
+ flock(fd, LOCK_UN);
+ close(fd);
+}
+
+void buildid_dir_write_lock(int *fd)
+{
+ *fd = buildid_dir_lock(LOCK_EX);
+}
+
+void buildid_dir_read_lock(int *fd)
+{
+ *fd = buildid_dir_lock(LOCK_SH);
+}
+
+void buildid_dir_write_unlock(int fd)
+{
+ buildid_dir_unlock(fd);
+}
+
+void buildid_dir_read_unlock(int fd)
+{
+ buildid_dir_unlock(fd);
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 8501122..326cd2e 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -31,4 +31,9 @@ int build_id_cache__add_s(const char *sbuild_id,
int build_id_cache__remove_s(const char *sbuild_id);
void disable_buildid_cache(void);
+void buildid_dir_write_lock(int *);
+void buildid_dir_read_lock(int *);
+void buildid_dir_write_unlock(int);
+void buildid_dir_read_unlock(int);
+
#endif
--
2.4.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 7:28 [PATCH 0/2] Add perf debug dir locking Milos Vyletel
2015-05-14 7:28 ` [PATCH 1/2] perf/tools: add read/write buildid dir locks Milos Vyletel
@ 2015-05-14 7:28 ` Milos Vyletel
2015-05-14 10:40 ` Ingo Molnar
1 sibling, 1 reply; 12+ messages in thread
From: Milos Vyletel @ 2015-05-14 7:28 UTC (permalink / raw)
To: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Milos Vyletel, Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
Use new read/write locks when accesing buildid directory on places where
we may race if multiple instances are run simultaneously.
Signed-off-by: Milos Vyletel <milos@redhat.com>
---
tools/perf/builtin-buildid-cache.c | 12 +++++++++++
tools/perf/util/build-id.c | 41 ++++++++++++++++++++++++++++++--------
2 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index d47a0cd..4cf0a1d 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -94,8 +94,13 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
char to_subdir[PATH_MAX];
struct dirent *dent;
int ret = -1;
+ int lockfd;
DIR *d;
+ buildid_dir_read_lock(&lockfd);
+ if (lockfd == -1)
+ return -1;
+
d = opendir(to_dir);
if (!d)
return -1;
@@ -121,6 +126,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
}
closedir(d);
+ buildid_dir_read_unlock(lockfd);
return ret;
}
@@ -130,6 +136,7 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
char from_dir[PATH_MAX], to_dir[PATH_MAX];
char *p;
+ int lockfd;
strlcpy(from_dir, filename, sizeof(from_dir));
@@ -156,6 +163,10 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
buildid_dir, sbuildid, dir);
+ buildid_dir_write_lock(&lockfd);
+ if (lockfd == -1)
+ return -1;
+
if (mkdir_p(to_dir, 0755))
return -1;
@@ -176,6 +187,7 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
}
return -1;
}
+ buildid_dir_write_unlock(lockfd);
pr_debug("kcore added to build-id cache directory %s\n", to_dir);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 46c41e1..13d23aa 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -17,6 +17,7 @@
#include "tool.h"
#include "header.h"
#include "vdso.h"
+#include <sys/file.h>
static bool no_buildid_cache;
@@ -308,6 +309,7 @@ int build_id_cache__list_build_ids(const char *pathname,
DIR *dir;
struct dirent *d;
int ret = 0;
+ int lockfd = -1;
list = strlist__new(true, NULL);
dir_name = build_id_cache__dirname_from_path(pathname, false, false);
@@ -316,11 +318,17 @@ int build_id_cache__list_build_ids(const char *pathname,
goto out;
}
+ buildid_dir_read_lock(&lockfd);
+ if (lockfd == -1) {
+ ret = -errno;
+ goto out;
+ }
+
/* List up all dirents */
dir = opendir(dir_name);
if (!dir) {
ret = -errno;
- goto out;
+ goto out_unlock;
}
while ((d = readdir(dir)) != NULL) {
@@ -330,6 +338,8 @@ int build_id_cache__list_build_ids(const char *pathname,
}
closedir(dir);
+out_unlock:
+ buildid_dir_read_unlock(lockfd);
out:
free(dir_name);
if (ret)
@@ -347,6 +357,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
char *realname = NULL, *filename = NULL, *dir_name = NULL,
*linkname = zalloc(size), *targetname, *tmp;
int err = -1;
+ int lockfd;
if (!is_kallsyms) {
realname = realpath(name, NULL);
@@ -358,30 +369,34 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
if (!dir_name)
goto out_free;
- if (mkdir_p(dir_name, 0755))
+ buildid_dir_write_lock(&lockfd);
+ if (lockfd == -1)
goto out_free;
+ if (mkdir_p(dir_name, 0755))
+ goto out_unlock;
+
if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
filename = NULL;
- goto out_free;
+ goto out_unlock;
}
if (access(filename, F_OK)) {
if (is_kallsyms) {
if (copyfile("/proc/kallsyms", filename))
- goto out_free;
+ goto out_unlock;
} else if (link(realname, filename) && errno != EEXIST &&
copyfile(name, filename))
- goto out_free;
+ goto out_unlock;
}
if (!build_id__filename(sbuild_id, linkname, size))
- goto out_free;
+ goto out_unlock;
tmp = strrchr(linkname, '/');
*tmp = '\0';
if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
- goto out_free;
+ goto out_unlock;
*tmp = '/';
targetname = filename + strlen(buildid_dir) - 5;
@@ -389,6 +404,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
if (symlink(targetname, linkname) == 0)
err = 0;
+out_unlock:
+ buildid_dir_write_unlock(lockfd);
out_free:
if (!is_kallsyms)
free(realname);
@@ -427,6 +444,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
char *filename = zalloc(size),
*linkname = zalloc(size), *tmp;
int err = -1;
+ int lockfd = -1;
if (filename == NULL || linkname == NULL)
goto out_free;
@@ -449,10 +467,17 @@ int build_id_cache__remove_s(const char *sbuild_id)
tmp = strrchr(linkname, '/') + 1;
snprintf(tmp, size - (tmp - linkname), "%s", filename);
- if (unlink(linkname))
+ buildid_dir_write_lock(&lockfd);
+ if (lockfd == -1)
goto out_free;
+ if (unlink(linkname))
+ goto out_unlock;
+
+
err = 0;
+out_unlock:
+ buildid_dir_write_unlock(lockfd);
out_free:
free(filename);
free(linkname);
--
2.4.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 7:28 ` [PATCH 2/2] perf/tools: put new buildid locks to use Milos Vyletel
@ 2015-05-14 10:40 ` Ingo Molnar
2015-05-14 11:38 ` Jiri Olsa
0 siblings, 1 reply; 12+ messages in thread
From: Ingo Molnar @ 2015-05-14 10:40 UTC (permalink / raw)
To: Milos Vyletel
Cc: Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
* Milos Vyletel <milos@redhat.com> wrote:
> Use new read/write locks when accesing buildid directory on places where
> we may race if multiple instances are run simultaneously.
Dunno, this will create locking interaction between multiple instances
of perf - hanging each other, etc.
And it seems unnecessary: the buildid hierarchy is already spread out.
What kind of races might there be?
Thanks,
Ingo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 10:40 ` Ingo Molnar
@ 2015-05-14 11:38 ` Jiri Olsa
2015-05-14 15:44 ` Milos Vyletel
2015-05-14 17:38 ` Ingo Molnar
0 siblings, 2 replies; 12+ messages in thread
From: Jiri Olsa @ 2015-05-14 11:38 UTC (permalink / raw)
To: Ingo Molnar
Cc: Milos Vyletel, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
>
> * Milos Vyletel <milos@redhat.com> wrote:
>
> > Use new read/write locks when accesing buildid directory on places where
> > we may race if multiple instances are run simultaneously.
>
> Dunno, this will create locking interaction between multiple instances
> of perf - hanging each other, etc.
>
> And it seems unnecessary: the buildid hierarchy is already spread out.
> What kind of races might there be?
there was just recently one fixed by commit:
0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
havent checked the final patch yet, but the idea is to
protect us from similar bugs
jirka
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 11:38 ` Jiri Olsa
@ 2015-05-14 15:44 ` Milos Vyletel
2015-05-14 17:38 ` Ingo Molnar
2015-05-14 17:38 ` Ingo Molnar
1 sibling, 1 reply; 12+ messages in thread
From: Milos Vyletel @ 2015-05-14 15:44 UTC (permalink / raw)
To: Jiri Olsa
Cc: Ingo Molnar, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
> On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> >
> > * Milos Vyletel <milos@redhat.com> wrote:
> >
> > > Use new read/write locks when accesing buildid directory on places where
> > > we may race if multiple instances are run simultaneously.
> >
> > Dunno, this will create locking interaction between multiple instances
> > of perf - hanging each other, etc.
> >
> > And it seems unnecessary: the buildid hierarchy is already spread out.
> > What kind of races might there be?
>
> there was just recently one fixed by commit:
> 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
>
> havent checked the final patch yet, but the idea is to
> protect us from similar bugs
right. on top of race with EEXIST couple more are possible (EMLINK,
ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to lock
this kind of operations and make sure we run one at a time.
Milos
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 11:38 ` Jiri Olsa
2015-05-14 15:44 ` Milos Vyletel
@ 2015-05-14 17:38 ` Ingo Molnar
2015-05-20 7:27 ` Milos Vyletel
2015-06-03 11:13 ` Milos Vyletel
1 sibling, 2 replies; 12+ messages in thread
From: Ingo Molnar @ 2015-05-14 17:38 UTC (permalink / raw)
To: Jiri Olsa
Cc: Milos Vyletel, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
* Milos Vyletel <milos@redhat.com> wrote:
> On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
>
> > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > >
> > > * Milos Vyletel <milos@redhat.com> wrote:
> > >
> > > > Use new read/write locks when accesing buildid directory on places where
> > > > we may race if multiple instances are run simultaneously.
> > >
> > > Dunno, this will create locking interaction between multiple instances
> > > of perf - hanging each other, etc.
> > >
> > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > What kind of races might there be?
> >
> > there was just recently one fixed by commit:
> > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> >
> > havent checked the final patch yet, but the idea is to
> > protect us from similar bugs
>
> right. on top of race with EEXIST couple more are possible (EMLINK,
> ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> lock this kind of operations and make sure we run one at a time.
Yeah, so the race pointed out in 0635b0f71424 can be (and should be)
fixed without locking:
- first create the file under a process-private name under
~/.debug/tmp/ if the target does not exist yet
- then fully fill it in with content
- then link(2) it to the public target name, which VFS operation is
atomic and may fail safely: at which point it got already created
by someone else.
- finally unlink() the private instance name and the target will now
be the only instance left: either created by us, or by some other
perf instance in the rare racy case.
Since all of ~/.debug is on the same filesystem this should work fine.
Beyond avoiding locking this approach has another advantage: it's
transaction safe, so a crashed/interrupted perf instance won't corrupt
the debug database, it will only put fully constructed files into the
public build-id namespace. It at most leaves a stale private file
around in ~/.debug/tmp/.
Really, we should be following the example of Git, which is using a
similar append-mostly flow to handle data, and generally avoids file
locking as much as possible - which is a whole new can of worms.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 15:44 ` Milos Vyletel
@ 2015-05-14 17:38 ` Ingo Molnar
0 siblings, 0 replies; 12+ messages in thread
From: Ingo Molnar @ 2015-05-14 17:38 UTC (permalink / raw)
To: Milos Vyletel
Cc: Jiri Olsa, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
* Milos Vyletel <milos@redhat.com> wrote:
> On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
>
> > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > >
> > > * Milos Vyletel <milos@redhat.com> wrote:
> > >
> > > > Use new read/write locks when accesing buildid directory on places where
> > > > we may race if multiple instances are run simultaneously.
> > >
> > > Dunno, this will create locking interaction between multiple instances
> > > of perf - hanging each other, etc.
> > >
> > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > What kind of races might there be?
> >
> > there was just recently one fixed by commit:
> > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> >
> > havent checked the final patch yet, but the idea is to
> > protect us from similar bugs
>
> right. on top of race with EEXIST couple more are possible (EMLINK,
> ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> lock this kind of operations and make sure we run one at a time.
No, that's not the only way to avoid the race - see my previous mail.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 17:38 ` Ingo Molnar
@ 2015-05-20 7:27 ` Milos Vyletel
2015-06-03 11:13 ` Milos Vyletel
1 sibling, 0 replies; 12+ messages in thread
From: Milos Vyletel @ 2015-05-20 7:27 UTC (permalink / raw)
To: Ingo Molnar
Cc: Jiri Olsa, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
On Thu, May 14, 2015 at 07:38:08PM +0200, Ingo Molnar wrote:
>
> * Milos Vyletel <milos@redhat.com> wrote:
>
> > On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
> >
> > > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > > >
> > > > * Milos Vyletel <milos@redhat.com> wrote:
> > > >
> > > > > Use new read/write locks when accesing buildid directory on places where
> > > > > we may race if multiple instances are run simultaneously.
> > > >
> > > > Dunno, this will create locking interaction between multiple instances
> > > > of perf - hanging each other, etc.
> > > >
> > > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > > What kind of races might there be?
> > >
> > > there was just recently one fixed by commit:
> > > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> > >
> > > havent checked the final patch yet, but the idea is to
> > > protect us from similar bugs
> >
> > right. on top of race with EEXIST couple more are possible (EMLINK,
> > ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> > lock this kind of operations and make sure we run one at a time.
>
> Yeah, so the race pointed out in 0635b0f71424 can be (and should be)
> fixed without locking:
>
> - first create the file under a process-private name under
> ~/.debug/tmp/ if the target does not exist yet
>
> - then fully fill it in with content
>
> - then link(2) it to the public target name, which VFS operation is
> atomic and may fail safely: at which point it got already created
> by someone else.
>
> - finally unlink() the private instance name and the target will now
> be the only instance left: either created by us, or by some other
> perf instance in the rare racy case.
>
> Since all of ~/.debug is on the same filesystem this should work fine.
>
> Beyond avoiding locking this approach has another advantage: it's
> transaction safe, so a crashed/interrupted perf instance won't corrupt
> the debug database, it will only put fully constructed files into the
> public build-id namespace. It at most leaves a stale private file
> around in ~/.debug/tmp/.
>
> Really, we should be following the example of Git, which is using a
> similar append-mostly flow to handle data, and generally avoids file
> locking as much as possible - which is a whole new can of worms.
>
Thanks Ingo. I'll take a look at this later this week.
Milos
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-05-14 17:38 ` Ingo Molnar
2015-05-20 7:27 ` Milos Vyletel
@ 2015-06-03 11:13 ` Milos Vyletel
2015-06-03 11:21 ` Ingo Molnar
1 sibling, 1 reply; 12+ messages in thread
From: Milos Vyletel @ 2015-06-03 11:13 UTC (permalink / raw)
To: Ingo Molnar
Cc: Jiri Olsa, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
On Thu, May 14, 2015 at 07:38:08PM +0200, Ingo Molnar wrote:
>
> * Milos Vyletel <milos@redhat.com> wrote:
>
> > On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
> >
> > > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > > >
> > > > * Milos Vyletel <milos@redhat.com> wrote:
> > > >
> > > > > Use new read/write locks when accesing buildid directory on places where
> > > > > we may race if multiple instances are run simultaneously.
> > > >
> > > > Dunno, this will create locking interaction between multiple instances
> > > > of perf - hanging each other, etc.
> > > >
> > > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > > What kind of races might there be?
> > >
> > > there was just recently one fixed by commit:
> > > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> > >
> > > havent checked the final patch yet, but the idea is to
> > > protect us from similar bugs
> >
> > right. on top of race with EEXIST couple more are possible (EMLINK,
> > ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> > lock this kind of operations and make sure we run one at a time.
>
> Yeah, so the race pointed out in 0635b0f71424 can be (and should be)
> fixed without locking:
>
> - first create the file under a process-private name under
> ~/.debug/tmp/ if the target does not exist yet
>
> - then fully fill it in with content
>
> - then link(2) it to the public target name, which VFS operation is
> atomic and may fail safely: at which point it got already created
> by someone else.
>
> - finally unlink() the private instance name and the target will now
> be the only instance left: either created by us, or by some other
> perf instance in the rare racy case.
>
> Since all of ~/.debug is on the same filesystem this should work fine.
>
> Beyond avoiding locking this approach has another advantage: it's
> transaction safe, so a crashed/interrupted perf instance won't corrupt
> the debug database, it will only put fully constructed files into the
> public build-id namespace. It at most leaves a stale private file
> around in ~/.debug/tmp/.
>
Ingo,
I finally found some time to make this change. While going over the code
I've noticed one thing that would make concurrent creation even easier
to solve. Instead of copying the file to temp file what about simply
opening file with O_CREAT|O_EXCL? creat itself
"creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC."
addition of O_EXCL would
"Ensure that this call creates the file: if this flag is specified in
conjunction with O_CREAT, and pathname already exists, then open() will fail."
This we would prevent truncation of already linked file in case link()
races as in 0635b0f71424. What do you think?
Milos
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-06-03 11:13 ` Milos Vyletel
@ 2015-06-03 11:21 ` Ingo Molnar
2015-06-03 11:27 ` Milos Vyletel
0 siblings, 1 reply; 12+ messages in thread
From: Ingo Molnar @ 2015-06-03 11:21 UTC (permalink / raw)
To: Milos Vyletel
Cc: Jiri Olsa, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
* Milos Vyletel <milos@redhat.com> wrote:
> On Thu, May 14, 2015 at 07:38:08PM +0200, Ingo Molnar wrote:
>
> >
> > * Milos Vyletel <milos@redhat.com> wrote:
> >
> > > On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
> > >
> > > > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > > > >
> > > > > * Milos Vyletel <milos@redhat.com> wrote:
> > > > >
> > > > > > Use new read/write locks when accesing buildid directory on places where
> > > > > > we may race if multiple instances are run simultaneously.
> > > > >
> > > > > Dunno, this will create locking interaction between multiple instances
> > > > > of perf - hanging each other, etc.
> > > > >
> > > > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > > > What kind of races might there be?
> > > >
> > > > there was just recently one fixed by commit:
> > > > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> > > >
> > > > havent checked the final patch yet, but the idea is to
> > > > protect us from similar bugs
> > >
> > > right. on top of race with EEXIST couple more are possible (EMLINK,
> > > ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> > > lock this kind of operations and make sure we run one at a time.
> >
> > Yeah, so the race pointed out in 0635b0f71424 can be (and should be)
> > fixed without locking:
> >
> > - first create the file under a process-private name under
> > ~/.debug/tmp/ if the target does not exist yet
> >
> > - then fully fill it in with content
> >
> > - then link(2) it to the public target name, which VFS operation is
> > atomic and may fail safely: at which point it got already created
> > by someone else.
> >
> > - finally unlink() the private instance name and the target will now
> > be the only instance left: either created by us, or by some other
> > perf instance in the rare racy case.
> >
> > Since all of ~/.debug is on the same filesystem this should work fine.
> >
> > Beyond avoiding locking this approach has another advantage: it's
> > transaction safe, so a crashed/interrupted perf instance won't corrupt
> > the debug database, it will only put fully constructed files into the
> > public build-id namespace. It at most leaves a stale private file
> > around in ~/.debug/tmp/.
> >
>
> Ingo,
>
> I finally found some time to make this change. While going over the code I've
> noticed one thing that would make concurrent creation even easier to solve.
> Instead of copying the file to temp file what about simply opening file with
> O_CREAT|O_EXCL? creat itself
>
> "creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC."
>
> addition of O_EXCL would
>
> "Ensure that this call creates the file: if this flag is specified in
> conjunction with O_CREAT, and pathname already exists, then open() will fail."
>
> This we would prevent truncation of already linked file in case link() races as
> in 0635b0f71424. What do you think?
But it would not prevent the problem of creating a not yet fully constructed file
- which some other tool invocation could attempt to parse in an incomplete
fashion.
Using create+link+unlink avoids that race, the files in the publicly visible
namespace will always be fully constructed by the time they are made visible
(atomically).
Thanks,
Ingo
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] perf/tools: put new buildid locks to use
2015-06-03 11:21 ` Ingo Molnar
@ 2015-06-03 11:27 ` Milos Vyletel
0 siblings, 0 replies; 12+ messages in thread
From: Milos Vyletel @ 2015-06-03 11:27 UTC (permalink / raw)
To: Ingo Molnar
Cc: Jiri Olsa, Peter Zijlstra, Paul Mackerras, Ingo Molnar,
Arnaldo Carvalho de Melo, Masami Hiramatsu, Namhyung Kim,
Jiri Olsa, He Kuang, Adrian Hunter,
open list:PERFORMANCE EVENT...
On Wed, Jun 03, 2015 at 01:21:41PM +0200, Ingo Molnar wrote:
>
> * Milos Vyletel <milos@redhat.com> wrote:
>
> > On Thu, May 14, 2015 at 07:38:08PM +0200, Ingo Molnar wrote:
> >
> > >
> > > * Milos Vyletel <milos@redhat.com> wrote:
> > >
> > > > On Thu, May 14, 2015 at 01:38:21PM +0200, Jiri Olsa wrote:
> > > >
> > > > > On Thu, May 14, 2015 at 12:40:59PM +0200, Ingo Molnar wrote:
> > > > > >
> > > > > > * Milos Vyletel <milos@redhat.com> wrote:
> > > > > >
> > > > > > > Use new read/write locks when accesing buildid directory on places where
> > > > > > > we may race if multiple instances are run simultaneously.
> > > > > >
> > > > > > Dunno, this will create locking interaction between multiple instances
> > > > > > of perf - hanging each other, etc.
> > > > > >
> > > > > > And it seems unnecessary: the buildid hierarchy is already spread out.
> > > > > > What kind of races might there be?
> > > > >
> > > > > there was just recently one fixed by commit:
> > > > > 0635b0f71424 perf tools: Fix race in build_id_cache__add_s()
> > > > >
> > > > > havent checked the final patch yet, but the idea is to
> > > > > protect us from similar bugs
> > > >
> > > > right. on top of race with EEXIST couple more are possible (EMLINK,
> > > > ENOSPC, EDQUOT, ENOMEM... the only way to prevent them all is to
> > > > lock this kind of operations and make sure we run one at a time.
> > >
> > > Yeah, so the race pointed out in 0635b0f71424 can be (and should be)
> > > fixed without locking:
> > >
> > > - first create the file under a process-private name under
> > > ~/.debug/tmp/ if the target does not exist yet
> > >
> > > - then fully fill it in with content
> > >
> > > - then link(2) it to the public target name, which VFS operation is
> > > atomic and may fail safely: at which point it got already created
> > > by someone else.
> > >
> > > - finally unlink() the private instance name and the target will now
> > > be the only instance left: either created by us, or by some other
> > > perf instance in the rare racy case.
> > >
> > > Since all of ~/.debug is on the same filesystem this should work fine.
> > >
> > > Beyond avoiding locking this approach has another advantage: it's
> > > transaction safe, so a crashed/interrupted perf instance won't corrupt
> > > the debug database, it will only put fully constructed files into the
> > > public build-id namespace. It at most leaves a stale private file
> > > around in ~/.debug/tmp/.
> > >
> >
> > Ingo,
> >
> > I finally found some time to make this change. While going over the code I've
> > noticed one thing that would make concurrent creation even easier to solve.
> > Instead of copying the file to temp file what about simply opening file with
> > O_CREAT|O_EXCL? creat itself
> >
> > "creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC."
> >
> > addition of O_EXCL would
> >
> > "Ensure that this call creates the file: if this flag is specified in
> > conjunction with O_CREAT, and pathname already exists, then open() will fail."
> >
> > This we would prevent truncation of already linked file in case link() races as
> > in 0635b0f71424. What do you think?
>
> But it would not prevent the problem of creating a not yet fully constructed file
> - which some other tool invocation could attempt to parse in an incomplete
> fashion.
>
> Using create+link+unlink avoids that race, the files in the publicly visible
> namespace will always be fully constructed by the time they are made visible
> (atomically).
>
Got it. Will use the approach proposed by you.
Milos
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-06-03 11:27 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-14 7:28 [PATCH 0/2] Add perf debug dir locking Milos Vyletel
2015-05-14 7:28 ` [PATCH 1/2] perf/tools: add read/write buildid dir locks Milos Vyletel
2015-05-14 7:28 ` [PATCH 2/2] perf/tools: put new buildid locks to use Milos Vyletel
2015-05-14 10:40 ` Ingo Molnar
2015-05-14 11:38 ` Jiri Olsa
2015-05-14 15:44 ` Milos Vyletel
2015-05-14 17:38 ` Ingo Molnar
2015-05-14 17:38 ` Ingo Molnar
2015-05-20 7:27 ` Milos Vyletel
2015-06-03 11:13 ` Milos Vyletel
2015-06-03 11:21 ` Ingo Molnar
2015-06-03 11:27 ` Milos Vyletel
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.