It's very simple, I'll paste the patch here for easy review and just attach the new init.d: -- /usr/portage/sci-biology/foldingathome/files/init-5.0.2-r5 2006-06-16 03:44:04.000000000 -0500 +++ /etc/init.d/foldingathome 2010-02-05 14:09:16.317227007 -0600 @@ -29,10 +29,11 @@ start() { do_config su foldingathome -c /opt/foldingathome/copy_client_config + IONICE_CMD=`which ionice 2>/dev/null && echo -c 3` for (($CPU; CPU > 0; CPU--)); do ebegin "Starting Folding@Home on CPU ${CPU}" cd /opt/foldingathome/client${CPU}/ - start-stop-daemon --chdir ${PWD} --chuid foldingathome --nicelevel 19 --start --background --exec ./foldingathome -- ${FOLD_OPTS} + ${IONICE_CMD} start-stop-daemon --chdir ${PWD} --chuid foldingathome --nicelevel 19 --start --background --exec ./foldingathome -- ${FOLD_OPTS} eend $? done }
Created attachment 218571 [details] Revised init.d script This adds the check for ionice executable and construction of the ionice command to set it to idle priority (if ionice is available). This only works if you're using the CFQ scheduler in your kernel config, but I'm fairly certain that invoking the ionice executable when you're not using this I/O scheduler will simply have no effect (not error an exit). I've also cleaned up whitespace a bit so that it's consistent. Indentation was a mixture of tabs & spaces before and it's now all tabs.
With CFQ (and what is the reason to use anything else, btw?) ionice is inherited from nice. If we really need to set ionice separately from nice then feature request for openrc should be opened. Again to set nice level it SSD_NICELEVEL variable that could be set in conf.d file. BTW, I think forcing --nice in init.d scrtipt is not good idea. Probably it's better to make it configurable: drop --nice 19 from init script and add SSD_NICELEVEL=19 into conf.d file. That said, reassigning on maintainer.
(In reply to comment #2) > With CFQ (and what is the reason to use anything else, btw?) ionice is > inherited from nice. Ahh, I wasn't aware of this inheritance, thanks for that info! :) However, when I/O niceness is not explicitly set, it seems that class will still be "best effort" (IOPRIO_CLASS_BE), which isn't quite as "nice" as idle (IOPRIO_CLASS_IDLE). Also, the mappings between CPU niceness and effective I/O nicencess in the "best effort" class are more coarse. Snippet from the ionice man page: Idle A program running with idle io priority will only get disk time when no other program has asked for disk io for a defined grace period. The impact of idle io processes on normal system activity should be zero. This scheduling class does not take a priority argument. Presently, this scheduling class is permit- ted for an ordinary user (since kernel 2.6.25). Best effort This is the effective scheduling class for any process that has not asked for a specific io priority. This class takes a priority argument from 0-7, with lower number being higher priority. Programs running at the same best effort priority are served in a round-robin fashion. A process that has not asked for an io priority formally uses "none" as scheduling class, but the io scheduler will treat such processes as if it were in the best effort class. The priority within the best effort class will be dynamically derived from the cpu nice level of the process: io_priority = (cpu_nice + 20) / 5. Still, you're right that the impact of explicitly setting I/O niceness is at least lessened since the kernel does this for us. Just note that using the idle class has a lower priority than any setting in the "best effort" class. I suppose others could argue convincingly that they wouldn't want it set to idle because it means no I/O unless there's nothing using the disk. Therefore, say when copying very large files, the fah processes could be completely I/O starved, even though the CPU was not at capacity. Also, I agree that niceness should be in conf.d, although I think that 19 is an appropriate default value. The default for portage is 15, which is fitting as well, since you can have them both running and portage will get priority and you should still get mostly descent "foreground" app performance.
Oh, one more thing. Note that when I/O niceness isn't explicitly set, the class is set to "none" and priority zero. I suppose this simply means that the kernel will decide its self what to use (based upon CPU niceness), so running "ionice -p xxx" won't display this derived value.
For CFQ both ioprio and ioprio_class are inherited from nice. Take a look at block/cfq-iosched.c: static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc) { .... ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio); switch (ioprio_class) { default: printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class); case IOPRIO_CLASS_NONE: /* * no prio set, inherit CPU scheduling settings */ cfqq->ioprio = task_nice_ioprio(tsk); cfqq->ioprio_class = task_nice_ioclass(tsk); break; ... } and task_nice_ioclass is defined in include/linux/ioprio.h: static inline int task_nice_ioclass(struct task_struct *task) { if (task->policy == SCHED_IDLE) return IOPRIO_CLASS_IDLE; else if (task->policy == SCHED_FIFO || task->policy == SCHED_RR) return IOPRIO_CLASS_RT; else return IOPRIO_CLASS_BE; } Thus ioclass is inherited too. Yes, running 'ionice -p ...' will just show that ionice was not redefined, hence inherited from nice.
Well, you're a good deal more knowledgeable about this than I, so I think I should trust you on this. I was never aware that Linux tasks had a policy (class), I thought it was just a niceness from 19 to -20. How do you set the class from userspace? Or are the classes simply derived from the niceness value? Wow, the definition for task_struct is 317 lines long! (closing bug)
Well, I guess sched_setscheduler is the exported kernel function to change the task policy class, but I don't see anywhere in the kernel where it explicitly sets it to SCHED_IDLE. I've also discovered that the chrt userspace utility from the util-linux-ng package is what you use to set it (./Documentation/scheduler/sched-design-CFS.txt), but I don't see the start-stop-daemon command having anything to do with that. So from what I can tell, the ioniceness is left in the "best effort" class, but the priority is set to the lowest available in that class, so that's definitely more than I anticipated. I may be splitting hairs to argue the value of truly changing the class to IDLE, so I'm leaving this bug closed. Also, some may argue that the behavior would be undesirable under heavy I/O loads and low CPU loads, when fah would only need a small slice of I/O in order to utilize a large amount of otherwise unused CPU.