/* * Generic synctask interface for channel program syncfuncs. * * To perform some action in syncing context, we'd generally call * dsl_sync_task(), but since the Lua script is already running inside a * synctask we need to leave out some actions (such as acquiring the config * rwlock and performing space checks). * * If 'sync' is false, executes a dry run and returns the error code. * * If we are not running in syncing context and we are not doing a dry run * (meaning we are running a zfs.sync function in open-context) then we * return a Lua error. * * This function also handles common fatal error cases for channel program * library functions. If a fatal error occurs, err_dsname will be the dataset * name reported in error messages, if supplied. */ static int zcp_sync_task(lua_State *state, dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc, void *arg, boolean_t sync, const char *err_dsname) { int err; zcp_run_info_t *ri = zcp_run_info(state); err = checkfunc(arg, ri->zri_tx); if (!sync) return (err); if (!ri->zri_sync) { return (luaL_error(state, "running functions from the zfs.sync " "submodule requires passing sync=TRUE to " "lzc_channel_program() (i.e. do not specify the \"-n\" " "command line argument)")); } if (err == 0) { syncfunc(arg, ri->zri_tx); } else if (err == EIO) { if (err_dsname != NULL) { return (luaL_error(state, "I/O error while accessing dataset '%s'", err_dsname)); } else { return (luaL_error(state, "I/O error while accessing dataset.")); } } return (err); }
/* * retrieves "cookie" in "value" * returns 0 if OK * 1 if no cookie at all * 2 if no cookie by the name "cookie" found * 3 if cookie value contains unwanted characters */ int flateGetCookie(char *value, int valuesz, char *cookie, int (*checkfunc)(int c)) { char *ptr; char buf[MAXCOOKIESIZE + 1]; int sz; ptr = getenv("HTTP_COOKIE"); if (!ptr) { value[0] = '\0'; return(1); } while (*ptr != '\0') { while (isspace(*ptr) || *ptr == ';') ptr++; sz = 0; while (sz < MAXCOOKIESIZE && ptr[sz] != '\0' && !isspace(ptr[sz]) && ptr[sz] != ';' && ptr[sz] != '=') { buf[sz] = ptr[sz]; sz++; } buf[sz] = '\0'; if (stricmp(buf, cookie)) { /* according to RFC 2965, cookie names are case insensitive */ ptr += sz; while (*ptr != '\0' && *ptr != ';') ptr++; continue; } ptr += sz; while (isspace(*ptr)) ptr++; if (*ptr != '=') { while (*ptr != '\0' && *ptr != ';') ptr++; continue; } ptr++; while (isspace(*ptr)) ptr++; sz = 0; while (sz < valuesz && ptr[sz] != '\0' && !isspace(ptr[sz]) && ptr[sz] != ';') { if (checkfunc && !checkfunc(ptr[sz])) { /* check for unwanted characaters */ value[0] = '\0'; return(3); } value[sz] = ptr[sz]; sz++; } value[sz] = '\0'; return(0); } return(2); }
int _waitfor( __const char *path, int delay_ms, int poll_ms, int (*checkfunc)(__const char *, void *), void *handle ) { int notify_id = -1; struct sigevent event; int chid = -1, coid = -1; struct _pulse pulse; int ret_val = -1; uint64_t polltimeout = 100 * (uint64_t)1000000; uint64_t timeout_nsec; timeout_nsec = _syspage_time(CLOCK_MONOTONIC); timeout_nsec += delay_ms * (uint64_t)1000000; /* Check to make sure we don't wait for something already there... */ ret_val = checkfunc( path, handle ); if ( ret_val >= 0 || ret_val == WAITFOR_CHECK_ABORT ) { return ret_val; } if ( poll_ms > 0 ) { polltimeout = poll_ms * (uint64_t)1000000; } /* * We make the channel fixed since we want to remain at the current * thread's priority */ chid = ChannelCreate(_NTO_CHF_FIXED_PRIORITY); if ( chid == -1 ) { goto fail1; } coid = ConnectAttach( ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0 ); if ( coid == -1 ) { goto fail2; } SIGEV_PULSE_INIT( &event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_PATHSPACE, 0 ); notify_id = procmgr_event_notify_add( PROCMGR_EVENT_PATHSPACE, &event ); if ( notify_id == -1 ) { goto fail3; } while(_syspage_time(CLOCK_MONOTONIC) < timeout_nsec) { /* we need to poll in case we are checking for a subdirectory/file, * since we won't get a pathmgr event for those. */ SIGEV_UNBLOCK_INIT(&event); if ( TimerTimeout( CLOCK_MONOTONIC, _NTO_TIMEOUT_RECEIVE, &event, &polltimeout, NULL) == -1 ) { ret_val = -1; break; } if ( MsgReceivePulse( chid, &pulse, sizeof(pulse), NULL ) != -1 || errno == ETIMEDOUT ) { ret_val = checkfunc( path, handle ); if ( ret_val >= 0 || ret_val == WAITFOR_CHECK_ABORT ) { break; } } else { break; } } (void)procmgr_event_notify_delete( notify_id ); fail3: (void)ConnectDetach(coid); fail2: (void)ChannelDestroy(chid); fail1: return ret_val; }