+static inline int
+get_thread_atime_policy(struct uthread *ut)
+{
+ return (ut->uu_flag & UT_ATIME_UPDATE)? IOPOL_ATIME_UPDATES_OFF: IOPOL_ATIME_UPDATES_DEFAULT;
+}
+
+static inline void
+set_thread_atime_policy(struct uthread *ut, int policy)
+{
+ if (policy == IOPOL_ATIME_UPDATES_OFF) {
+ ut->uu_flag |= UT_ATIME_UPDATE;
+ } else {
+ ut->uu_flag &= ~UT_ATIME_UPDATE;
+ }
+}
+
+static inline void
+set_task_atime_policy(struct proc *p, int policy)
+{
+ if (policy == IOPOL_ATIME_UPDATES_OFF) {
+ OSBitOrAtomic16((uint16_t)P_VFS_IOPOLICY_ATIME_UPDATES, &p->p_vfs_iopolicy);
+ } else {
+ OSBitAndAtomic16(~((uint16_t)P_VFS_IOPOLICY_ATIME_UPDATES), &p->p_vfs_iopolicy);
+ }
+}
+
+static inline int
+get_task_atime_policy(struct proc *p)
+{
+ return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_ATIME_UPDATES)? IOPOL_ATIME_UPDATES_OFF: IOPOL_ATIME_UPDATES_DEFAULT;
+}
+
+static int
+iopolicysys_vfs_atime_updates(struct proc *p __unused, int cmd, int scope, int policy, struct _iopol_param_t *iop_param)
+{
+ int error = 0;
+ thread_t thread;
+
+ /* Validate scope */
+ switch (scope) {
+ case IOPOL_SCOPE_THREAD:
+ thread = current_thread();
+ break;
+ case IOPOL_SCOPE_PROCESS:
+ thread = THREAD_NULL;
+ break;
+ default:
+ error = EINVAL;
+ goto out;
+ }
+
+ /* Validate policy */
+ if (cmd == IOPOL_CMD_SET) {
+ switch (policy) {
+ case IOPOL_ATIME_UPDATES_DEFAULT:
+ case IOPOL_ATIME_UPDATES_OFF:
+ break;
+ default:
+ error = EINVAL;
+ goto out;
+ }
+ }
+
+ /* Perform command */
+ switch(cmd) {
+ case IOPOL_CMD_SET:
+ if (thread != THREAD_NULL)
+ set_thread_atime_policy(get_bsdthread_info(thread), policy);
+ else
+ set_task_atime_policy(p, policy);
+ break;
+ case IOPOL_CMD_GET:
+ if (thread != THREAD_NULL)
+ policy = get_thread_atime_policy(get_bsdthread_info(thread));
+ else
+ policy = get_task_atime_policy(p);
+ iop_param->iop_policy = policy;
+ break;
+ default:
+ error = EINVAL; /* unknown command */
+ break;
+ }
+
+out:
+ return (error);
+}