/** * Parses \<numaddr_range\> token of the syntax. * * \retval 1 if \a str parses to \<number\> | \<expr_list\> * \retval 0 otherwise */ static int num_parse(char *str, int len, cfs_list_t *list, unsigned min, unsigned max) { __u32 num; struct lstr src; struct numaddr_range *numaddr; src.ls_str = str; src.ls_len = len; LIBCFS_ALLOC(numaddr, sizeof(struct numaddr_range)); if (numaddr == NULL) return 0; cfs_list_add_tail(&numaddr->nar_link, list); CFS_INIT_LIST_HEAD(&numaddr->nar_range_exprs); if (libcfs_str2num_check(src.ls_str, src.ls_len, &num, min, max)) { /* <number> */ struct range_expr *expr; LIBCFS_ALLOC(expr, sizeof(struct range_expr)); if (expr == NULL) return 0; expr->re_lo = expr->re_hi = num; expr->re_stride = 1; cfs_list_add_tail(&expr->re_link, &numaddr->nar_range_exprs); return 1; } return parse_expr_list(&src, &numaddr->nar_range_exprs, min, max); }
int lst_batch_add_ioctl(lstio_batch_add_args_t *args) { int rc; char *name; if (args->lstio_bat_key != console_session.ses_key) return -EACCES; if (args->lstio_bat_namep == NULL || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); if (name == NULL) return -ENOMEM; if (cfs_copy_from_user(name, args->lstio_bat_namep, args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } name[args->lstio_bat_nmlen] = 0; rc = lstcon_batch_add(name); LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return rc; }
static int lnet_selftest_init(void) { int nscheds; int rc; int i; rc = cfs_wi_sched_create("lst_s", lnet_cpt_table(), CFS_CPT_ANY, 1, &lst_sched_serial); if (rc != 0) { CERROR("Failed to create serial WI scheduler for LST\n"); return rc; } lst_init_step = LST_INIT_WI_SERIAL; nscheds = cfs_cpt_number(lnet_cpt_table()); LIBCFS_ALLOC(lst_sched_test, sizeof(lst_sched_test[0]) * nscheds); if (lst_sched_test == NULL) goto error; lst_init_step = LST_INIT_WI_TEST; for (i = 0; i < nscheds; i++) { int nthrs = cfs_cpt_weight(lnet_cpt_table(), i); /* reserve at least one CPU for LND */ nthrs = max(nthrs - 1, 1); rc = cfs_wi_sched_create("lst_t", lnet_cpt_table(), i, nthrs, &lst_sched_test[i]); if (rc != 0) { CERROR("Failed to create CPT affinity WI scheduler %d for LST\n", i); goto error; } } rc = srpc_startup(); if (rc != 0) { CERROR("LST can't startup rpc\n"); goto error; } lst_init_step = LST_INIT_RPC; rc = sfw_startup(); if (rc != 0) { CERROR("LST can't startup framework\n"); goto error; } lst_init_step = LST_INIT_FW; rc = lstcon_console_init(); if (rc != 0) { CERROR("LST can't startup console\n"); goto error; } lst_init_step = LST_INIT_CONSOLE; return 0; error: lnet_selftest_fini(); return rc; }
static int lst_batch_run_ioctl(lstio_batch_run_args_t *args) { int rc; char *name; if (args->lstio_bat_key != console_session.ses_key) return -EACCES; if (!args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } name[args->lstio_bat_nmlen] = 0; rc = lstcon_batch_run(name, args->lstio_bat_timeout, args->lstio_bat_resultp); LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return rc; }
static int lst_group_add_ioctl(struct lstio_group_add_args *args) { char *name; int rc; if (args->lstio_grp_key != console_session.ses_key) return -EACCES; if (args->lstio_grp_namep == NULL|| args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen); return -EFAULT; } name[args->lstio_grp_nmlen] = 0; rc = lstcon_group_add(name); LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return rc; }
static int lst_batch_stop_ioctl(struct lstio_batch_stop_args *args) { int rc; char *name; if (args->lstio_bat_key != console_session.ses_key) return -EACCES; if (args->lstio_bat_resultp == NULL || args->lstio_bat_namep == NULL || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } name[args->lstio_bat_nmlen] = 0; rc = lstcon_batch_stop(name, args->lstio_bat_force, args->lstio_bat_resultp); LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return rc; }
static int lst_session_new_ioctl(struct lstio_session_new_args *args) { char *name; int rc; if (args->lstio_ses_idp == NULL || /* address for output sid */ args->lstio_ses_key == 0 || /* no key is specified */ args->lstio_ses_namep == NULL || /* session name */ args->lstio_ses_nmlen <= 0 || args->lstio_ses_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_ses_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_ses_namep, args->lstio_ses_nmlen)) { LIBCFS_FREE(name, args->lstio_ses_nmlen + 1); return -EFAULT; } name[args->lstio_ses_nmlen] = 0; rc = lstcon_session_new(name, args->lstio_ses_key, args->lstio_ses_feats, args->lstio_ses_force, args->lstio_ses_timeout, args->lstio_ses_idp); LIBCFS_FREE(name, args->lstio_ses_nmlen + 1); return rc; }
/* Handle incoming ZC request from sender. * NB: it's called only from read_handler, so we're sure that * the conn cannot become zombie in the middle of processing */ int usocklnd_handle_zc_req(usock_peer_t *peer, __u64 cookie) { usock_conn_t *conn; usock_zc_ack_t *zc_ack; int type; int rc; int dummy; LIBCFS_ALLOC (zc_ack, sizeof(*zc_ack)); if (zc_ack == NULL) return -ENOMEM; zc_ack->zc_cookie = cookie; /* Let's assume that CONTROL is the best type for zcack, * but userspace clients don't use typed connections */ if (the_lnet.ln_pid & LNET_PID_USERFLAG) type = SOCKLND_CONN_ANY; else type = SOCKLND_CONN_CONTROL; rc = usocklnd_find_or_create_conn(peer, type, &conn, NULL, zc_ack, &dummy); if (rc != 0) { LIBCFS_FREE (zc_ack, sizeof(*zc_ack)); return rc; } usocklnd_conn_decref(conn); return 0; }
static int lst_group_del_ioctl(lstio_group_del_args_t *args) { int rc; char *name; if (args->lstio_grp_key != console_session.ses_key) return -EACCES; if (!args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } name[args->lstio_grp_nmlen] = 0; rc = lstcon_group_del(name); LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return rc; }
int cfs_wi_startup (void) { int i; int n; int rc; cfs_wi_data.wi_nthreads = 0; cfs_wi_data.wi_nsched = CFS_WI_NSCHED; LIBCFS_ALLOC(cfs_wi_data.wi_scheds, cfs_wi_data.wi_nsched * sizeof(cfs_wi_sched_t)); if (cfs_wi_data.wi_scheds == NULL) return -ENOMEM; cfs_spin_lock_init(&cfs_wi_data.wi_glock); for (i = 0; i < cfs_wi_data.wi_nsched; i++) cfs_wi_sched_init(&cfs_wi_data.wi_scheds[i]); #ifdef __KERNEL__ n = cfs_num_online_cpus(); for (i = 0; i <= n; i++) { rc = cfs_wi_start_thread(cfs_wi_scheduler, (void *)(long_ptr_t)(i == n ? -1 : i)); if (rc != 0) { CERROR ("Can't spawn workitem scheduler: %d\n", rc); cfs_wi_shutdown(); return rc; } } #else n = rc = 0; #endif return 0; }
static int lst_group_update_ioctl(lstio_group_update_args_t *args) { int rc; char *name; if (args->lstio_grp_key != console_session.ses_key) return -EACCES; if (args->lstio_grp_resultp == NULL || args->lstio_grp_namep == NULL || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } name[args->lstio_grp_nmlen] = 0; switch (args->lstio_grp_opc) { case LST_GROUP_CLEAN: rc = lstcon_group_clean(name, args->lstio_grp_args); break; case LST_GROUP_REFRESH: rc = lstcon_group_refresh(name, args->lstio_grp_resultp); break; case LST_GROUP_RMND: if (args->lstio_grp_count <= 0 || args->lstio_grp_idsp == NULL) { rc = -EINVAL; break; } rc = lstcon_nodes_remove(name, args->lstio_grp_count, args->lstio_grp_idsp, args->lstio_grp_resultp); break; default: rc = -EINVAL; break; } LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return rc; }
int LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, lnet_handle_eq_t *handle) { lnet_eq_t *eq; LASSERT (the_lnet.ln_init); LASSERT (the_lnet.ln_refcount > 0); /* We need count to be a power of 2 so that when eq_{enq,deq}_seq * overflow, they don't skip entries, so the queue has the same * apparant capacity at all times */ if (count != LOWEST_BIT_SET(count)) { /* not a power of 2 already */ do { /* knock off all but the top bit... */ count &= ~LOWEST_BIT_SET (count); } while (count != LOWEST_BIT_SET(count)); count <<= 1; /* ...and round up */ } if (count == 0) /* catch bad parameter / overflow on roundup */ return (-EINVAL); eq = lnet_eq_alloc(); if (eq == NULL) return (-ENOMEM); LIBCFS_ALLOC(eq->eq_events, count * sizeof(lnet_event_t)); if (eq->eq_events == NULL) { LNET_LOCK(); lnet_eq_free (eq); LNET_UNLOCK(); return -ENOMEM; } /* NB this resets all event sequence numbers to 0, to be earlier * than eq_deq_seq */ memset(eq->eq_events, 0, count * sizeof(lnet_event_t)); eq->eq_deq_seq = 1; eq->eq_enq_seq = 1; eq->eq_size = count; eq->eq_refcount = 0; eq->eq_callback = callback; LNET_LOCK(); lnet_initialise_handle (&eq->eq_lh, LNET_COOKIE_TYPE_EQ); list_add (&eq->eq_list, &the_lnet.ln_active_eqs); LNET_UNLOCK(); lnet_eq2handle(handle, eq); return (0); }
int lwt_init () { int i; int j; for (i = 0; i < cfs_num_online_cpus(); i++) if (lwt_cpus[i].lwtc_current_page != NULL) return (-EALREADY); LASSERT (!lwt_enabled); /* NULL pointers, zero scalars */ memset (lwt_cpus, 0, sizeof (lwt_cpus)); lwt_pages_per_cpu = LWT_MEMORY / (cfs_num_online_cpus() * PAGE_CACHE_SIZE); for (i = 0; i < cfs_num_online_cpus(); i++) for (j = 0; j < lwt_pages_per_cpu; j++) { struct page *page = alloc_page(GFP_KERNEL); lwt_page_t *lwtp; if (page == NULL) { CERROR ("Can't allocate page\n"); lwt_fini (); return (-ENOMEM); } LIBCFS_ALLOC(lwtp, sizeof (*lwtp)); if (lwtp == NULL) { CERROR ("Can't allocate lwtp\n"); __free_page(page); lwt_fini (); return (-ENOMEM); } lwtp->lwtp_page = page; lwtp->lwtp_events = page_address(page); memset(lwtp->lwtp_events, 0, PAGE_CACHE_SIZE); if (j == 0) { CFS_INIT_LIST_HEAD (&lwtp->lwtp_list); lwt_cpus[i].lwtc_current_page = lwtp; } else { cfs_list_add (&lwtp->lwtp_list, &lwt_cpus[i].lwtc_current_page->lwtp_list); } } lwt_enabled = 1; cfs_mb(); LWT_EVENT(0,0,0,0); return (0); }
struct lnet_xport * lx_new(struct lnet_xport_int *lxi) { struct lnet_xport *lx; LIBCFS_ALLOC(lx, sizeof(*lx)); if (lx) lx->lx_tab = lxi; return (lx); }
int libcfs_socketpair(cfs_socket_t **sockp) { int rc, i, fdp[2]; LIBCFS_ALLOC(sockp[0], sizeof(cfs_socket_t)); if (sockp[0] == NULL) { CERROR ("Can't alloc memory for cfs_socket_t (1)\n"); return -ENOMEM; } LIBCFS_ALLOC(sockp[1], sizeof(cfs_socket_t)); if (sockp[1] == NULL) { CERROR ("Can't alloc memory for cfs_socket_t (2)\n"); LIBCFS_FREE(sockp[0], sizeof(cfs_socket_t)); return -ENOMEM; } rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fdp); if (rc != 0) { rc = -errno; CERROR ("Cannot create socket pair\n"); LIBCFS_FREE(sockp[0], sizeof(cfs_socket_t)); LIBCFS_FREE(sockp[1], sizeof(cfs_socket_t)); return rc; } sockp[0]->s_fd = fdp[0]; sockp[1]->s_fd = fdp[1]; for (i = 0; i < 2; i++) { rc = libcfs_fcntl_nonblock(sockp[i]); if (rc) { libcfs_sock_release(sockp[0]); libcfs_sock_release(sockp[1]); return rc; } } return 0; }
/** * Finds or creates struct nidrange. * * Checks if \a src is a valid network name, looks for corresponding * nidrange on the ist of nidranges (\a nidlist), creates new struct * nidrange if it is not found. * * \retval pointer to struct nidrange matching network specified via \a src * \retval NULL if \a src does not match any network */ static struct nidrange * add_nidrange(const struct lstr *src, cfs_list_t *nidlist) { struct netstrfns *nf; struct nidrange *nr; int endlen; unsigned netnum; if (src->ls_len >= LNET_NIDSTR_SIZE) return NULL; nf = libcfs_namenum2netstrfns(src->ls_str); if (nf == NULL) return NULL; endlen = src->ls_len - strlen(nf->nf_name); if (endlen == 0) /* network name only, e.g. "elan" or "tcp" */ netnum = 0; else { /* e.g. "elan25" or "tcp23", refuse to parse if * network name is not appended with decimal or * hexadecimal number */ if (!libcfs_str2num_check(src->ls_str + strlen(nf->nf_name), endlen, &netnum, 0, MAX_NUMERIC_VALUE)) return NULL; } cfs_list_for_each_entry(nr, nidlist, nr_link) { if (nr->nr_netstrfns != nf) continue; if (nr->nr_netnum != netnum) continue; return nr; } LIBCFS_ALLOC(nr, sizeof(struct nidrange)); if (nr == NULL) return NULL; cfs_list_add_tail(&nr->nr_link, nidlist); CFS_INIT_LIST_HEAD(&nr->nr_addrranges); nr->nr_netstrfns = nf; nr->nr_all = 0; nr->nr_netnum = netnum; return nr; }
/* called when opening /dev/device */ static int libcfs_psdev_open(unsigned long flags, void *args) { struct libcfs_device_userstate *ldu; ENTRY; try_module_get(THIS_MODULE); LIBCFS_ALLOC(ldu, sizeof(*ldu)); if (ldu != NULL) { ldu->ldu_memhog_pages = 0; ldu->ldu_memhog_root_page = NULL; } *(struct libcfs_device_userstate **)args = ldu; RETURN(0); }
/** * Parses \<range_expr\> token of the syntax. * * \retval pointer to allocated range_expr and initialized * range_expr::re_lo, range_expr::re_hi and range_expr:re_stride if \a `* src parses to * \<number\> | * \<number\> '-' \<number\> | * \<number\> '-' \<number\> '/' \<number\> * \retval NULL othersize */ static struct range_expr * parse_range_expr(struct lstr *src, unsigned min, unsigned max) { struct lstr tok; struct range_expr *expr; LIBCFS_ALLOC(expr, sizeof(struct range_expr)); if (expr == NULL) return NULL; if (libcfs_str2num_check(src->ls_str, src->ls_len, &expr->re_lo, min, max)) { /* <number> is parsed */ expr->re_hi = expr->re_lo; expr->re_stride = 1; return expr; } if (!gettok(src, '-', &tok)) goto failed; if (!libcfs_str2num_check(tok.ls_str, tok.ls_len, &expr->re_lo, min, max)) goto failed; /* <number> - */ if (libcfs_str2num_check(src->ls_str, src->ls_len, &expr->re_hi, min, max)) { /* <number> - <number> is parsed */ expr->re_stride = 1; return expr; } /* go to check <number> '-' <number> '/' <number> */ if (gettok(src, '/', &tok)) { if (!libcfs_str2num_check(tok.ls_str, tok.ls_len, &expr->re_hi, min, max)) goto failed; /* <number> - <number> / ... */ if (libcfs_str2num_check(src->ls_str, src->ls_len, &expr->re_stride, min, max)) /* <number> - <number> / <number> is parsed */ return expr; } failed: LIBCFS_FREE(expr, sizeof(struct range_expr)); return NULL; }
static int lst_stat_query_ioctl(struct lstio_stat_args *args) { int rc; char *name = NULL; /* TODO: not finished */ if (args->lstio_sta_key != console_session.ses_key) return -EACCES; if (args->lstio_sta_resultp == NULL) return -EINVAL; if (args->lstio_sta_idsp != NULL) { if (args->lstio_sta_count <= 0) return -EINVAL; rc = lstcon_nodes_stat(args->lstio_sta_count, args->lstio_sta_idsp, args->lstio_sta_timeout, args->lstio_sta_resultp); } else if (args->lstio_sta_namep != NULL) { if (args->lstio_sta_nmlen <= 0 || args->lstio_sta_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1); if (name == NULL) return -ENOMEM; rc = copy_from_user(name, args->lstio_sta_namep, args->lstio_sta_nmlen); if (rc == 0) rc = lstcon_group_stat(name, args->lstio_sta_timeout, args->lstio_sta_resultp); else rc = -EFAULT; } else { rc = -EINVAL; } if (name != NULL) LIBCFS_FREE(name, args->lstio_sta_nmlen + 1); return rc; }
int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) { int a; int b; int c; int d; int n = nob; /* XscanfX */ /* numeric IP? */ if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && n == nob && (a & ~0xff) == 0 && (b & ~0xff) == 0 && (c & ~0xff) == 0 && (d & ~0xff) == 0) { *addr = ((a<<24)|(b<<16)|(c<<8)|d); return 1; } #if !defined(__KERNEL__) && defined HAVE_GETHOSTBYNAME /* known hostname? */ if (('a' <= str[0] && str[0] <= 'z') || ('A' <= str[0] && str[0] <= 'Z')) { char *tmp; LIBCFS_ALLOC(tmp, nob + 1); if (tmp != NULL) { struct hostent *he; memcpy(tmp, str, nob); tmp[nob] = 0; he = gethostbyname(tmp); LIBCFS_FREE(tmp, nob); if (he != NULL) { __u32 ip = *(__u32 *)he->h_addr; *addr = ntohl(ip); return 1; } } } #endif return 0; }
struct cfs_cpt_table * cfs_cpt_table_alloc(unsigned int ncpt) { struct cfs_cpt_table *cptab; if (ncpt != 1) { CERROR("Can't support cpu partition number %d\n", ncpt); return NULL; } LIBCFS_ALLOC(cptab, sizeof(*cptab)); if (cptab != NULL) { cptab->ctb_version = CFS_CPU_VERSION_MAGIC; cptab->ctb_nparts = ncpt; } return cptab; }
static int lst_nodes_add_ioctl(struct lstio_group_nodes_args *args) { unsigned feats; int rc; char *name; if (args->lstio_grp_key != console_session.ses_key) return -EACCES; if (args->lstio_grp_idsp == NULL || /* array of ids */ args->lstio_grp_count <= 0 || args->lstio_grp_resultp == NULL || args->lstio_grp_featp == NULL || args->lstio_grp_namep == NULL || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } name[args->lstio_grp_nmlen] = 0; rc = lstcon_nodes_add(name, args->lstio_grp_count, args->lstio_grp_idsp, &feats, args->lstio_grp_resultp); LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); if (rc == 0 && copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) { return -EINVAL; } return rc; }
int libcfs_sock_create(cfs_socket_t **sockp, int *fatal, __u32 local_ip, int local_port) { int rc, fd, option; *fatal = 1; LIBCFS_ALLOC(*sockp, sizeof(cfs_socket_t)); if (*sockp == NULL) { CERROR("Can't alloc memory for cfs_socket_t\n"); return -ENOMEM; } fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { rc = -errno; CERROR("Cannot create socket: %d\n", rc); LIBCFS_FREE(*sockp, sizeof(cfs_socket_t)); return rc; } (*sockp)->s_fd = fd; option = 1; rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); if (rc != 0) { rc = -errno; CERROR("Cannot set SO_REUSEADDR for socket: %d\n", rc); libcfs_sock_release(*sockp); return rc; } rc = libcfs_sock_bind(*sockp, local_ip, local_port); if (rc != 0) { *fatal = 0; libcfs_sock_release(*sockp); } return rc; }
/** * Parses \<addrrange\> token on the syntax. * * Allocates struct addrrange and links to \a nidrange via * (nidrange::nr_addrranges) * * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\> * \retval -errno otherwise */ static int parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange) { struct addrrange *addrrange; if (src->ls_len == 1 && src->ls_str[0] == '*') { nidrange->nr_all = 1; return 0; } LIBCFS_ALLOC(addrrange, sizeof(struct addrrange)); if (addrrange == NULL) return -ENOMEM; list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges); INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges); return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str, src->ls_len, &addrrange->ar_numaddr_ranges); }
static int lst_batch_query_ioctl(lstio_batch_query_args_t *args) { char *name; int rc; if (args->lstio_bat_key != console_session.ses_key) return -EACCES; if (args->lstio_bat_resultp == NULL || args->lstio_bat_namep == NULL || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; if (args->lstio_bat_testidx < 0) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); if (name == NULL) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } name[args->lstio_bat_nmlen] = 0; rc = lstcon_test_batch_query(name, args->lstio_bat_testidx, args->lstio_bat_client, args->lstio_bat_timeout, args->lstio_bat_resultp); LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return rc; }
int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, struct libcfs_ioctl_hdr __user *uhdr) { struct libcfs_ioctl_hdr hdr; int err = 0; ENTRY; if (copy_from_user(&hdr, uhdr, sizeof(hdr))) RETURN(-EFAULT); if (hdr.ioc_version != LIBCFS_IOCTL_VERSION && hdr.ioc_version != LIBCFS_IOCTL_VERSION2) { CERROR("libcfs ioctl: version mismatch expected %#x, got %#x\n", LIBCFS_IOCTL_VERSION, hdr.ioc_version); RETURN(-EINVAL); } if (hdr.ioc_len < sizeof(struct libcfs_ioctl_hdr)) { CERROR("libcfs ioctl: user buffer too small for ioctl\n"); RETURN(-EINVAL); } if (hdr.ioc_len > LIBCFS_IOC_DATA_MAX) { CERROR("libcfs ioctl: user buffer is too large %d/%d\n", hdr.ioc_len, LIBCFS_IOC_DATA_MAX); RETURN(-EINVAL); } LIBCFS_ALLOC(*hdr_pp, hdr.ioc_len); if (*hdr_pp == NULL) RETURN(-ENOMEM); if (copy_from_user(*hdr_pp, uhdr, hdr.ioc_len)) GOTO(failed, err = -EFAULT); RETURN(0); failed: LIBCFS_FREE(*hdr_pp, hdr.ioc_len); RETURN(err); }
static int __proc_cpt_table(void *data, int write, loff_t pos, void __user *buffer, int nob) { char *buf = NULL; int len = 4096; int rc = 0; if (write) return -EPERM; LASSERT(cfs_cpt_table != NULL); while (1) { LIBCFS_ALLOC(buf, len); if (buf == NULL) return -ENOMEM; rc = cfs_cpt_table_print(cfs_cpt_table, buf, len); if (rc >= 0) break; if (rc == -EFBIG) { LIBCFS_FREE(buf, len); len <<= 1; continue; } goto out; } if (pos >= rc) { rc = 0; goto out; } rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL); out: if (buf != NULL) LIBCFS_FREE(buf, len); return rc; }
int lst_nodes_add_ioctl(lstio_group_nodes_args_t *args) { int rc; char *name; if (args->lstio_grp_key != console_session.ses_key) return -EACCES; if (args->lstio_grp_idsp == NULL || /* array of ids */ args->lstio_grp_count <= 0 || args->lstio_grp_resultp == NULL || args->lstio_grp_namep == NULL || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); if (name == NULL) return -ENOMEM; if (cfs_copy_from_user(name, args->lstio_grp_namep, args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } name[args->lstio_grp_nmlen] = 0; rc = lstcon_nodes_add(name, args->lstio_grp_count, args->lstio_grp_idsp, args->lstio_grp_resultp); LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return rc; }
struct lc_watchdog *lc_watchdog_add(int timeout, void (*callback)(pid_t, void *), void *data) { struct lc_watchdog *lcw = NULL; ENTRY; LIBCFS_ALLOC(lcw, sizeof(*lcw)); if (lcw == NULL) { CDEBUG(D_INFO, "Could not allocate new lc_watchdog\n"); RETURN(ERR_PTR(-ENOMEM)); } cfs_spin_lock_init(&lcw->lcw_lock); lcw->lcw_refcount = 1; /* refcount for owner */ lcw->lcw_task = cfs_current(); lcw->lcw_pid = cfs_curproc_pid(); lcw->lcw_callback = (callback != NULL) ? callback : lc_watchdog_dumplog; lcw->lcw_data = data; lcw->lcw_state = LC_WATCHDOG_DISABLED; CFS_INIT_LIST_HEAD(&lcw->lcw_list); cfs_timer_init(&lcw->lcw_timer, lcw_cb, lcw); cfs_down(&lcw_refcount_sem); if (++lcw_refcount == 1) lcw_dispatch_start(); cfs_up(&lcw_refcount_sem); /* Keep this working in case we enable them by default */ if (lcw->lcw_state == LC_WATCHDOG_ENABLED) { lcw->lcw_last_touched = cfs_time_current(); cfs_timer_arm(&lcw->lcw_timer, cfs_time_seconds(timeout) + cfs_time_current()); } RETURN(lcw); }
int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp, const struct libcfs_ioctl_hdr __user *uhdr) { struct libcfs_ioctl_hdr hdr; int err = 0; if (copy_from_user(&hdr, uhdr, sizeof(hdr))) return -EFAULT; if (hdr.ioc_version != LIBCFS_IOCTL_VERSION && hdr.ioc_version != LIBCFS_IOCTL_VERSION2) { CERROR("libcfs ioctl: version mismatch expected %#x, got %#x\n", LIBCFS_IOCTL_VERSION, hdr.ioc_version); return -EINVAL; } if (hdr.ioc_len < sizeof(struct libcfs_ioctl_data)) { CERROR("libcfs ioctl: user buffer too small for ioctl\n"); return -EINVAL; } if (hdr.ioc_len > LIBCFS_IOC_DATA_MAX) { CERROR("libcfs ioctl: user buffer is too large %d/%d\n", hdr.ioc_len, LIBCFS_IOC_DATA_MAX); return -EINVAL; } LIBCFS_ALLOC(*hdr_pp, hdr.ioc_len); if (!*hdr_pp) return -ENOMEM; if (copy_from_user(*hdr_pp, uhdr, hdr.ioc_len)) { LIBCFS_FREE(*hdr_pp, hdr.ioc_len); err = -EFAULT; } return err; }