@@ -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();
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@rasmusvillemoes.dk> --- kernel/workqueue.c | 54 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-)