+ copy->pl_refcnt = 1;
+ /* hang on to reference to old till process exits */
+ p->p_olimit = p->p_limit;
+ p->p_limit = copy;
+ proc_list_unlock();
+
+ return(0);
+}
+
+
+/*
+ * iopolicysys
+ *
+ * Description: System call MUX for use in manipulating I/O policy attributes of the current process or thread
+ *
+ * Parameters: cmd Policy command
+ * arg Pointer to policy arguments
+ *
+ * Returns: 0 Success
+ * EINVAL Invalid command or invalid policy arguments
+ *
+ */
+int
+iopolicysys(__unused struct proc *p, __unused struct iopolicysys_args *uap, __unused register_t *retval)
+{
+ int error = 0;
+ thread_t thread = THREAD_NULL;
+ int *policy;
+ struct uthread *ut = NULL;
+ struct _iopol_param_t iop_param;
+
+ if ((error = copyin(uap->arg, &iop_param, sizeof(iop_param))) != 0)
+ goto exit;
+
+ if (iop_param.iop_iotype != IOPOL_TYPE_DISK) {
+ error = EINVAL;
+ goto exit;
+ }
+
+ switch (iop_param.iop_scope) {
+ case IOPOL_SCOPE_PROCESS:
+ policy = &p->p_iopol_disk;
+ break;
+ case IOPOL_SCOPE_THREAD:
+ thread = current_thread();
+ ut = get_bsdthread_info(thread);
+ policy = &ut->uu_iopol_disk;
+ break;
+ default:
+ error = EINVAL;
+ goto exit;
+ }
+
+ switch(uap->cmd) {
+ case IOPOL_CMD_SET:
+ switch (iop_param.iop_policy) {
+ case IOPOL_DEFAULT:
+ case IOPOL_NORMAL:
+ case IOPOL_THROTTLE:
+ case IOPOL_PASSIVE:
+ proc_lock(p);
+ *policy = iop_param.iop_policy;
+ proc_unlock(p);
+ break;
+ default:
+ error = EINVAL;
+ goto exit;
+ }
+ break;
+ case IOPOL_CMD_GET:
+ switch (*policy) {
+ case IOPOL_DEFAULT:
+ case IOPOL_NORMAL:
+ case IOPOL_THROTTLE:
+ case IOPOL_PASSIVE:
+ iop_param.iop_policy = *policy;
+ break;
+ default: // in-kernel
+ // this should never happen
+ printf("%s: unknown I/O policy %d\n", __func__, *policy);
+ // restore to default value
+ *policy = IOPOL_DEFAULT;
+ iop_param.iop_policy = *policy;
+ }
+
+ error = copyout((caddr_t)&iop_param, uap->arg, sizeof(iop_param));
+ break;
+ default:
+ error = EINVAL; // unknown command
+ break;
+ }
+
+ exit:
+ *retval = error;
+ return (error);