|
@@ -1,4 +1,6 @@
|
|
|
#include <asm/bug.h>
|
|
|
+#include <sys/time.h>
|
|
|
+#include <sys/resource.h>
|
|
|
#include "symbol.h"
|
|
|
#include "dso.h"
|
|
|
#include "machine.h"
|
|
@@ -180,12 +182,20 @@ static int __open_dso(struct dso *dso, struct machine *machine)
|
|
|
return fd;
|
|
|
}
|
|
|
|
|
|
+static void check_data_close(void);
|
|
|
+
|
|
|
static int open_dso(struct dso *dso, struct machine *machine)
|
|
|
{
|
|
|
int fd = __open_dso(dso, machine);
|
|
|
|
|
|
- if (fd > 0)
|
|
|
+ if (fd > 0) {
|
|
|
dso__list_add(dso);
|
|
|
+ /*
|
|
|
+ * Check if we crossed the allowed number
|
|
|
+ * of opened DSOs and close one if needed.
|
|
|
+ */
|
|
|
+ check_data_close();
|
|
|
+ }
|
|
|
|
|
|
return fd;
|
|
|
}
|
|
@@ -204,6 +214,54 @@ static void close_dso(struct dso *dso)
|
|
|
close_data_fd(dso);
|
|
|
}
|
|
|
|
|
|
+static void close_first_dso(void)
|
|
|
+{
|
|
|
+ struct dso *dso;
|
|
|
+
|
|
|
+ dso = list_first_entry(&dso__data_open, struct dso, data.open_entry);
|
|
|
+ close_dso(dso);
|
|
|
+}
|
|
|
+
|
|
|
+static rlim_t get_fd_limit(void)
|
|
|
+{
|
|
|
+ struct rlimit l;
|
|
|
+ rlim_t limit = 0;
|
|
|
+
|
|
|
+ /* Allow half of the current open fd limit. */
|
|
|
+ if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
|
|
|
+ if (l.rlim_cur == RLIM_INFINITY)
|
|
|
+ limit = l.rlim_cur;
|
|
|
+ else
|
|
|
+ limit = l.rlim_cur / 2;
|
|
|
+ } else {
|
|
|
+ pr_err("failed to get fd limit\n");
|
|
|
+ limit = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return limit;
|
|
|
+}
|
|
|
+
|
|
|
+static bool may_cache_fd(void)
|
|
|
+{
|
|
|
+ static rlim_t limit;
|
|
|
+
|
|
|
+ if (!limit)
|
|
|
+ limit = get_fd_limit();
|
|
|
+
|
|
|
+ if (limit == RLIM_INFINITY)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return limit > (rlim_t) dso__data_open_cnt;
|
|
|
+}
|
|
|
+
|
|
|
+static void check_data_close(void)
|
|
|
+{
|
|
|
+ bool cache_fd = may_cache_fd();
|
|
|
+
|
|
|
+ if (!cache_fd)
|
|
|
+ close_first_dso();
|
|
|
+}
|
|
|
+
|
|
|
void dso__data_close(struct dso *dso)
|
|
|
{
|
|
|
close_dso(dso);
|
|
@@ -356,7 +414,6 @@ dso_cache__read(struct dso *dso, struct machine *machine,
|
|
|
if (ret <= 0)
|
|
|
free(cache);
|
|
|
|
|
|
- dso__data_close(dso);
|
|
|
return ret;
|
|
|
}
|
|
|
|