[RFC PATCH 2/2] workqueue: update sysfs handlers, allow setting RT policies

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For this POC, this (ab)uses the "nice" attribute.

It's of course not exactly pretty, but it avoids the problem of "what
to show in the xyz file when using SCHED_NORMAL, and what to show in
the nice file when using SCHED_RR/SCHED_FIFO".

It's backwards-compatible, in that a bare integer is interpreted as a
nice value, while an integer prefixed by "fifo:" or "rr:" chooses that
RT scheduling policy with the associated value as the priority. The
show method of course reflects what the store method accepts.

Signed-off-by: Rasmus Villemoes <linux@xxxxxxxxxxxxxxxxxx>
---
 kernel/workqueue.c | 54 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 47 insertions(+), 7 deletions(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9eb2ff7bcc04..a97f1aff809e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5538,13 +5538,34 @@ static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
 	struct workqueue_struct *wq = dev_to_wq(dev);
-	int written;
+	struct workqueue_attrs *wqattrs;
+	const char *pfx;
+	int val;
 
 	mutex_lock(&wq->mutex);
-	written = scnprintf(buf, PAGE_SIZE, "%d\n", wq->unbound_attrs->nice);
+	wqattrs = wq->unbound_attrs;
+	switch (wqattrs->policy) {
+	case SCHED_NORMAL:
+		pfx = "";
+		val = wqattrs->nice;
+		break;
+	case SCHED_FIFO:
+		pfx = "fifo:";
+		val = wqattrs->priority;
+		break;
+	case SCHED_RR:
+		pfx = "rr:";
+		val = wqattrs->priority;
+		break;
+	default:
+		/* Shouldn't happen. */
+		pfx = NULL;
+	}
 	mutex_unlock(&wq->mutex);
 
-	return written;
+	if (!pfx)
+		return -EIO;
+	return scnprintf(buf, PAGE_SIZE, "%s%d\n", pfx, val);
 }
 
 /* prepare workqueue_attrs for sysfs store operations */
@@ -5568,6 +5589,24 @@ static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
 	struct workqueue_struct *wq = dev_to_wq(dev);
 	struct workqueue_attrs *attrs;
 	int ret = -ENOMEM;
+	int policy, val;
+
+	if (sscanf(buf, "fifo:%d", &val) == 1)
+		policy = SCHED_FIFO;
+	else if (sscanf(buf, "rr:%d", &val) == 1)
+		policy = SCHED_RR;
+	else if (sscanf(buf, "%d", &val) == 1)
+		policy = SCHED_NORMAL;
+	else
+		return -EINVAL;
+
+	if (policy == SCHED_NORMAL) {
+		if (val < MIN_NICE || val > MAX_NICE)
+			return -EINVAL;
+	} else {
+		if (val <= 0 || val >= MAX_RT_PRIO)
+			return -EINVAL;
+	}
 
 	apply_wqattrs_lock();
 
@@ -5575,11 +5614,12 @@ static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
 	if (!attrs)
 		goto out_unlock;
 
-	if (sscanf(buf, "%d", &attrs->nice) == 1 &&
-	    attrs->nice >= MIN_NICE && attrs->nice <= MAX_NICE)
-		ret = apply_workqueue_attrs_locked(wq, attrs);
+	attrs->policy = policy;
+	if (policy == SCHED_NORMAL)
+		attrs->nice = val;
 	else
-		ret = -EINVAL;
+		attrs->priority = val;
+	ret = apply_workqueue_attrs_locked(wq, attrs);
 
 out_unlock:
 	apply_wqattrs_unlock();
-- 
2.31.1




[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux