int dm_get_mountinfo( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, size_t buflen, void *bufp, size_t *rlenp) { dm_fsreg_t *fsrp; dm_tokdata_t *tdp; int error; int lc; /* lock cookie */ /* Make sure that the caller's buffer is 8-byte aligned. */ if (((__psint_t)bufp & (sizeof(__u64) - 1)) != 0) return(EFAULT); /* Verify that the handle is a filesystem handle, and that the filesystem is capable of sending events. If not, return an error. */ error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_VFS, DM_RIGHT_SHARED, &tdp); if (error != 0) return(error); /* Find the filesystem entry. This should always succeed as the dm_app_get_tdp call created a filesystem reference. Once we find the entry, drop the lock. The mountinfo message is never modified, the filesystem entry can't disappear, and we don't want to hold a spinlock while doing copyout calls. */ fsrp = dm_find_fsreg_and_lock((fsid_t*)&tdp->td_handle.ha_fsid, &lc); if (fsrp == NULL) { dm_app_put_tdp(tdp); return(EINVAL); } mutex_spinunlock(&fsrp->fr_lock, lc); /* Copy the message into the user's buffer and update his 'rlenp'. */ if (put_user(fsrp->fr_msgsize, rlenp)) { error = EFAULT; } else if (fsrp->fr_msgsize > buflen) { /* user buffer not big enough */ error = E2BIG; } else if (copy_to_user(bufp, fsrp->fr_msg, fsrp->fr_msgsize)) { error = EFAULT; } else { error = 0; } dm_app_put_tdp(tdp); return(error); }
int dm_get_config_events( void *hanp, size_t hlen, u_int nelem, dm_eventset_t *eventsetp, u_int *nelemp) { dm_fsys_vector_t *fsys_vector; dm_tokdata_t *tdp; int error; /* Convert the handle into a vnode. */ if ((error = dm_get_config_tdp(hanp, hlen, &tdp)) != 0) return(error); /* Now call the filesystem-specific routine to determine the events supported by that filesystem. */ VN_BHV_READ_LOCK(VN_BHV_HEAD(tdp->td_vp)); fsys_vector = dm_fsys_vector(tdp->td_vp); error = fsys_vector->get_config_events(tdp->td_vp, tdp->td_right, nelem, eventsetp, nelemp); VN_BHV_READ_UNLOCK(VN_BHV_HEAD(tdp->td_vp)); dm_app_put_tdp(tdp); return(error); }
int dm_symlink_by_handle( dm_sessid_t sid, void *dirhanp, size_t dirhlen, dm_token_t token, void *hanp, size_t hlen, char *cname, char *path) { dm_fsys_vector_t *fsys_vector; dm_tokdata_t *tdp; int error; error = dm_app_get_tdp(sid, dirhanp, dirhlen, token, DM_TDT_DIR, DM_RIGHT_EXCL, &tdp); if (error != 0) return(error); fsys_vector = dm_fsys_vector(tdp->td_bdp); error = fsys_vector->symlink_by_handle(tdp->td_bdp, tdp->td_right, hanp, hlen, cname, path); dm_app_put_tdp(tdp); return(error); }
int dm_set_region( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, u_int nelem, dm_region_t *regbufp, dm_boolean_t *exactflagp) { dm_fsys_vector_t *fsys_vector; dm_tokdata_t *tdp; int error; error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_REG, DM_RIGHT_EXCL, &tdp); if (error != 0) return(error); VN_BHV_READ_LOCK(VN_BHV_HEAD(tdp->td_vp)); fsys_vector = dm_fsys_vector(tdp->td_vp); error = fsys_vector->set_region(tdp->td_vp, tdp->td_right, nelem, regbufp, exactflagp); VN_BHV_READ_UNLOCK(VN_BHV_HEAD(tdp->td_vp)); dm_app_put_tdp(tdp); return(error); }
int dm_get_config( void *hanp, size_t hlen, dm_config_t flagname, dm_size_t *retvalp) { dm_fsys_vector_t *fsys_vector; dm_tokdata_t *tdp; dm_size_t retval; int system = 1; int error; /* Trap and process configuration parameters which are system-wide. */ switch (flagname) { case DM_CONFIG_LEGACY: case DM_CONFIG_PENDING: case DM_CONFIG_OBJ_REF: retval = DM_TRUE; break; case DM_CONFIG_MAX_MESSAGE_DATA: retval = DM_MAX_MSG_DATA; break; default: system = 0; break; } if (system) { #ifdef __sgi if (copyout(&retval, retvalp, sizeof(retval))) return(EFAULT); #else if (copy_to_user(retvalp, &retval, sizeof(retval))) return(EFAULT); #endif return(0); } /* Must be filesystem-specific. Convert the handle into a vnode. */ if ((error = dm_get_config_tdp(hanp, hlen, &tdp)) != 0) return(error); /* Now call the filesystem-specific routine to determine the value of the configuration option for that filesystem. */ fsys_vector = dm_fsys_vector(tdp->td_bdp); error = fsys_vector->get_config(tdp->td_bdp, tdp->td_right, flagname, retvalp); dm_app_put_tdp(tdp); return(error); }
int dm_get_eventlist( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, u_int nelem, dm_eventset_t *eventsetp, u_int *nelemp) { dm_fsys_vector_t *fsys_vector; dm_tokdata_t *tdp; dm_eventset_t eventset; u_int elem; int error; if (nelem == 0) return(EINVAL); /* Access the specified object. */ error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_ANY, DM_RIGHT_SHARED, &tdp); if (error != 0) return(error); /* Get the object's event list. */ fsys_vector = dm_fsys_vector(tdp->td_bdp); error = fsys_vector->get_eventlist(tdp->td_bdp, tdp->td_right, (tdp->td_type == DM_TDT_VFS ? DM_FSYS_OBJ : 0), nelem, &eventset, &elem); dm_app_put_tdp(tdp); if (error) return(error); if (copy_to_user(eventsetp, &eventset, sizeof(eventset))) return(EFAULT); if (put_user(nelem, nelemp)) return(EFAULT); return(0); }
int dm_set_eventlist( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, dm_eventset_t *eventsetp, u_int maxevent) { dm_fsys_vector_t *fsys_vector; dm_eventset_t eventset; dm_tokdata_t *tdp; int error; if (copy_from_user(&eventset, eventsetp, sizeof(eventset))) return(EFAULT); /* Do some minor sanity checking. */ if (maxevent == 0 || maxevent > DM_EVENT_MAX) return(EINVAL); /* Access the specified object. */ error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_ANY, DM_RIGHT_EXCL, &tdp); if (error != 0) return(error); fsys_vector = dm_fsys_vector(tdp->td_bdp); error = fsys_vector->set_eventlist(tdp->td_bdp, tdp->td_right, (tdp->td_type == DM_TDT_VFS ? DM_FSYS_OBJ : 0), &eventset, maxevent); dm_app_put_tdp(tdp); return(error); }
int dm_set_return_on_destroy( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, dm_attrname_t *attrnamep, dm_boolean_t enable) { dm_attrname_t attrname; dm_tokdata_t *tdp; dm_fsreg_t *fsrp; dm_session_t *s; int error; int lc1; /* first lock cookie */ int lc2; /* second lock cookie */ /* If a dm_attrname_t is provided, copy it in and validate it. */ if (enable && (error = copy_from_user(&attrname, attrnamep, sizeof(attrname))) != 0) return(error); /* Validate the filesystem handle and use it to get the filesystem's disposition structure. */ error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_VFS, DM_RIGHT_EXCL, &tdp); if (error != 0) return(error); fsrp = dm_find_fsreg_and_lock((fsid_t*)&tdp->td_handle.ha_fsid, &lc1); if (fsrp == NULL) { dm_app_put_tdp(tdp); return(EINVAL); } /* Now that we own 'fsrp->fr_lock', get the lock on the session so that it can't disappear while we add it to the filesystem's event mask. */ if ((error = dm_find_session_and_lock(sid, &s, &lc2)) != 0) { mutex_spinunlock(&fsrp->fr_lock, lc1); dm_app_put_tdp(tdp); return(error); } /* A caller cannot disable return-on-destroy if he is not registered for DM_EVENT_DESTROY. Enabling return-on-destroy is an implicit dm_set_disp() for DM_EVENT_DESTROY; we wake up all processes waiting for a disposition in case any was waiting for a DM_EVENT_DESTROY event. */ error = 0; if (enable) { fsrp->fr_sessp[DM_EVENT_DESTROY] = s; fsrp->fr_rattr = attrname; if (fsrp->fr_dispcnt) sv_broadcast(&fsrp->fr_dispq); } else if (fsrp->fr_sessp[DM_EVENT_DESTROY] != s) { error = EINVAL; } else { bzero(&fsrp->fr_rattr, sizeof(fsrp->fr_rattr)); } mutex_spinunlock(&s->sn_qlock, lc2); /* reverse cookie order */ mutex_spinunlock(&fsrp->fr_lock, lc1); dm_app_put_tdp(tdp); return(error); }
int dm_set_disp( dm_sessid_t sid, void *hanp, size_t hlen, dm_token_t token, dm_eventset_t *eventsetp, u_int maxevent) { dm_session_t *s; dm_fsreg_t *fsrp; dm_tokdata_t *tdp; dm_eventset_t eventset; int error; int lc1; /* first lock cookie */ int lc2; /* second lock cookie */ u_int i; /* Copy in and validate the event mask. Only the lower maxevent bits are meaningful, so clear any bits set above maxevent. */ if (maxevent == 0 || maxevent > DM_EVENT_MAX) return(EINVAL); if (copy_from_user(&eventset, eventsetp, sizeof(eventset))) return(EFAULT); eventset &= (1 << maxevent) - 1; /* If the caller specified the global handle, then the only valid token is DM_NO_TOKEN, and the only valid event in the event mask is DM_EVENT_MOUNT. If it is set, add the session to the list of sessions that want to receive mount events. If it is clear, remove the session from the list. Since DM_EVENT_MOUNT events never block waiting for a session to register, there is noone to wake up if we do add the session to the list. */ if (DM_GLOBALHAN(hanp, hlen)) { if (token != DM_NO_TOKEN) return(EINVAL); if ((error = dm_find_session_and_lock(sid, &s, &lc1)) != 0) return(error); if (eventset == 0) { s->sn_flags &= ~DM_SN_WANTMOUNT; error = 0; } else if (eventset == 1 << DM_EVENT_MOUNT) { s->sn_flags |= DM_SN_WANTMOUNT; error = 0; } else { error = EINVAL; } mutex_spinunlock(&s->sn_qlock, lc1); return(error); } /* Since it's not the global handle, it had better be a filesystem handle. Verify that the first 'maxevent' events in the event list are all valid for a filesystem handle. */ if (eventset & ~DM_VALID_DISP_EVENTS) return(EINVAL); /* Verify that the session is valid, that the handle is a filesystem handle, and that the filesystem is capable of sending events. (If a dm_fsreg_t structure exists, then the filesystem can issue events.) */ error = dm_app_get_tdp(sid, hanp, hlen, token, DM_TDT_VFS, DM_RIGHT_EXCL, &tdp); if (error != 0) return(error); fsrp = dm_find_fsreg_and_lock((fsid_t*)&tdp->td_handle.ha_fsid, &lc1); if (fsrp == NULL) { dm_app_put_tdp(tdp); return(EINVAL); } /* Now that we own 'fsrp->fr_lock', get the lock on the session so that it can't disappear while we add it to the filesystem's event mask. */ if ((error = dm_find_session_and_lock(sid, &s, &lc2)) != 0) { mutex_spinunlock(&fsrp->fr_lock, lc1); dm_app_put_tdp(tdp); return(error); } /* Update the event disposition array for this filesystem, adding and/or removing the session as appropriate. If this session is dropping registration for DM_EVENT_DESTROY, or is overriding some other session's registration for DM_EVENT_DESTROY, then clear any any attr-on-destroy attribute name also. */ for (i = 0; i < DM_EVENT_MAX; i++) { if (DMEV_ISSET(i, eventset)) { if (i == DM_EVENT_DESTROY && fsrp->fr_sessp[i] != s) bzero(&fsrp->fr_rattr, sizeof(fsrp->fr_rattr)); fsrp->fr_sessp[i] = s; } else if (fsrp->fr_sessp[i] == s) { if (i == DM_EVENT_DESTROY) bzero(&fsrp->fr_rattr, sizeof(fsrp->fr_rattr)); fsrp->fr_sessp[i] = NULL; } } mutex_spinunlock(&s->sn_qlock, lc2); /* reverse cookie order */ /* Wake up all processes waiting for a disposition on this filesystem in case any of them happen to be waiting for an event which we just added. */ if (fsrp->fr_dispcnt) sv_broadcast(&fsrp->fr_dispq); mutex_spinunlock(&fsrp->fr_lock, lc1); dm_app_put_tdp(tdp); return(0); }