summaryrefslogtreecommitdiffstats
path: root/sys-utils/prlimit.c
diff options
context:
space:
mode:
authorBernhard Voelker2011-11-16 11:55:43 +0100
committerKarel Zak2011-11-16 11:55:43 +0100
commit044bc8de2d22a06f7253888460e7a32d4b367c8e (patch)
tree2c8d1a122ad8bc213a8a0c4a08830279576ff539 /sys-utils/prlimit.c
parentprlimit: fix error message (diff)
downloadkernel-qcow2-util-linux-044bc8de2d22a06f7253888460e7a32d4b367c8e.tar.gz
kernel-qcow2-util-linux-044bc8de2d22a06f7253888460e7a32d4b367c8e.tar.xz
kernel-qcow2-util-linux-044bc8de2d22a06f7253888460e7a32d4b367c8e.zip
prlimit: fix case when PID is given later
# prlimit --nofile=:4000 --pid $$ When the PID is given later than a partially given limit, then prlimit used the current PID for getting the missing part (hard, soft) of the limit. Factored out the retrieval of the unknown limit from parse_prlim() to new get_unknown_hardsoft() which is to be called by do_prlimit() based on the struct prlimit member 'modify' set by add_prlim(). [kzak@redhat.com: - use prlimit->mofify as mask - add soft vs. hard limit check from another Bernhard's patch] Signed-off-by: Bernhard Voelker <mail@bernhard-voelker.de> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/prlimit.c')
-rw-r--r--sys-utils/prlimit.c62
1 files changed, 33 insertions, 29 deletions
diff --git a/sys-utils/prlimit.c b/sys-utils/prlimit.c
index 02e520a3b..c60ba7b3d 100644
--- a/sys-utils/prlimit.c
+++ b/sys-utils/prlimit.c
@@ -86,7 +86,7 @@ static struct prlimit_desc prlimit_desc[] =
struct prlimit {
struct rlimit rlim;
struct prlimit_desc *desc;
- int modify;
+ int modify; /* PRLIMIT_{SOFT,HARD} mask */
};
#define PRLIMIT_EMPTY_LIMIT {{ 0, 0, }, NULL, 0 }
@@ -294,6 +294,25 @@ done:
return 0;
}
+/*
+ * If one of the limits is unknown (default value for not being passed), we
+ * need to get the current limit and use it. I see no other way other than
+ * using prlimit(2).
+ */
+static void get_unknown_hardsoft(struct prlimit *lim)
+{
+ struct rlimit old;
+
+ if (prlimit(pid, lim->desc->resource, NULL, &old) == -1)
+ err(EXIT_FAILURE, _("failed to get old %s limit"),
+ lim->desc->name);
+
+ if (!(lim->modify & PRLIMIT_SOFT))
+ lim->rlim.rlim_cur = old.rlim_cur;
+ else if (!(lim->modify & PRLIMIT_HARD))
+ lim->rlim.rlim_max = old.rlim_max;
+}
+
static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags)
{
size_t i, nshows = 0;
@@ -301,9 +320,17 @@ static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags)
for (i = 0; i < n; i++) {
struct rlimit *new = NULL;
- if (lims[i].modify)
+ if (lims[i].modify) {
+ if (lims[i].modify != (PRLIMIT_HARD | PRLIMIT_SOFT))
+ get_unknown_hardsoft(&lims[i]);
+
+ if ((lims[i].rlim.rlim_cur > lims[i].rlim.rlim_max) &&
+ (lims[i].rlim.rlim_cur != RLIM_INFINITY ||
+ lims[i].rlim.rlim_max != RLIM_INFINITY))
+ errx(EXIT_FAILURE, _("the soft limit %s cannot exceed the hard limit"),
+ lims[i].desc->name);
new = &lims[i].rlim;
- else
+ } else
nshows++;
if (verbose && new) {
@@ -404,31 +431,10 @@ static int parse_prlim(struct rlimit *lim, char *ops, size_t id)
errx(EXIT_FAILURE, _("failed to parse %s limit"),
prlimit_desc[id].name);
- /*
- * If one of the limits is unknown (default value for not being passed), we need
- * to get the current limit and use it.
- * I see no other way other than using prlimit(2).
- */
- if (found != (PRLIMIT_HARD | PRLIMIT_SOFT)) {
- struct rlimit old;
-
- if (prlimit(pid, prlimit_desc[id].resource, NULL, &old) == -1)
- errx(EXIT_FAILURE, _("failed to get old %s limit"),
- prlimit_desc[id].name);
-
- if (!(found & PRLIMIT_SOFT))
- soft = old.rlim_cur;
- else if (!(found & PRLIMIT_HARD))
- hard = old.rlim_max;
- }
-
- if (soft > hard && (soft != RLIM_INFINITY || hard != RLIM_INFINITY))
- errx(EXIT_FAILURE, _("the soft limit cannot exceed the ceiling value"));
-
lim->rlim_cur = soft;
lim->rlim_max = hard;
- return 0;
+ return found;
}
/*
@@ -438,10 +444,8 @@ static int add_prlim(char *ops, struct prlimit *lim, size_t id)
{
lim->desc = &prlimit_desc[id];
- if (ops) { /* planning on modifying a limit? */
- lim->modify = 1;
- parse_prlim(&lim->rlim, ops, id);
- }
+ if (ops)
+ lim->modify = parse_prlim(&lim->rlim, ops, id);
return 0;
}