static void list_update(list_t *list, lwp_info_t *lwp) { id_info_t *id; if (list->l_head == NULL) { /* first element */ list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t)); id_update(id, lwp, list->l_type); list->l_count++; return; } for (id = list->l_head; id; id = id->id_next) { if ((list->l_type == LT_PROCESS) && (id->id_pid != lwp->li_psinfo->pr_pid)) continue; if ((list->l_type == LT_USERS) && (id->id_uid != lwp->li_psinfo->pr_uid)) continue; if ((list->l_type == LT_PROJECTS) && (id->id_projid != lwp->li_psinfo->pr_projid)) continue; id_update(id, lwp, list->l_type); return; } /* a new element */ id = list->l_tail; id->id_next = Zalloc(sizeof (id_info_t)); id->id_next->id_prev = list->l_tail; id->id_next->id_next = NULL; list->l_tail = id->id_next; id = list->l_tail; id_update(id, lwp, list->l_type); list->l_count++; }
/* * get swap info */ static int get_swapinfo( struct swaptable **swtpp, int *nswap, md_error_t *ep ) { int i; size_t swtsize; *swtpp = NULL; /* get number of entries */ if ((*nswap = swapctl(SC_GETNSWP, NULL)) < 0) { return (mdsyserror(ep, errno, "swapctl(SC_GETNSWP)")); } /* allocate structure */ swtsize = sizeof ((*swtpp)->swt_n) + ((*nswap) * sizeof ((*swtpp)->swt_ent[0])); *swtpp = (struct swaptable *)Zalloc(swtsize); (*swtpp)->swt_n = *nswap; for (i = 0; (i < (*nswap)); ++i) (*swtpp)->swt_ent[i].ste_path = Zalloc(MAXPATHLEN); /* get info */ if (((*nswap) = swapctl(SC_LIST, (*swtpp))) < 0) { (void) mdsyserror(ep, errno, "swapctl(SC_LIST)"); free_swapinfo(*swtpp); return (-1); } /* return success */ return (0); }
/* * util_parse_add_replica -- (internal) add a new replica to the pool set info */ static int util_parse_add_replica(struct pool_set **setp) { LOG(3, "setp %p", setp); ASSERTne(setp, NULL); struct pool_set *set = *setp; ASSERTne(set, NULL); set = Realloc(set, sizeof(struct pool_set) + (set->nreplicas + 1) * sizeof(struct pool_replica *)); if (set == NULL) { ERR("!Realloc"); return -1; } *setp = set; struct pool_replica *rep; rep = Zalloc(sizeof(struct pool_replica)); if (rep == NULL) { ERR("!Malloc"); return -1; } unsigned r = set->nreplicas++; set->replica[r] = rep; return 0; }
/* * util_parse_add_remote_replica -- (internal) add a new remote replica * to the pool set info */ static int util_parse_add_remote_replica(struct pool_set **setp, char *node_addr, char *pool_desc) { LOG(3, "setp %p node_addr %s pool_desc %s", setp, node_addr, pool_desc); ASSERTne(setp, NULL); ASSERTne(node_addr, NULL); ASSERTne(pool_desc, NULL); int ret = util_parse_add_replica(setp); if (ret != 0) return ret; /* a remote replica has one 'fake' part */ ret = util_parse_add_part(*setp, NULL, 0); if (ret != 0) return ret; struct pool_set *set = *setp; struct pool_replica *rep = set->replica[set->nreplicas - 1]; ASSERTne(rep, NULL); rep->remote = Zalloc(sizeof(struct remote_replica)); if (rep->remote == NULL) { ERR("!Malloc"); return -1; } rep->remote->node_addr = node_addr; rep->remote->pool_desc = pool_desc; set->remote = 1; return 0; }
/* * replica_create_poolset_health_status -- create helping structure for storing * poolset's health status */ int replica_create_poolset_health_status(struct pool_set *set, struct poolset_health_status **set_hsp) { LOG(3, "set %p, set_hsp %p", set, set_hsp); unsigned nreplicas = set->nreplicas; struct poolset_health_status *set_hs; set_hs = Zalloc(sizeof(struct poolset_health_status) + nreplicas * sizeof(struct replica_health_status *)); if (set_hs == NULL) { ERR("!Zalloc for poolset health state"); return -1; } set_hs->nreplicas = nreplicas; for (unsigned i = 0; i < nreplicas; ++i) { struct replica_health_status *replica_hs = create_replica_health_status(set, i); if (replica_hs == NULL) { replica_free_poolset_health_status(set_hs); return -1; } set_hs->replica[i] = replica_hs; } *set_hsp = set_hs; return 0; }
/* * open RPC connection to rpc.metamhd */ static mhd_handle_t * open_metamhd( char *hostname, md_error_t *ep ) { CLIENT *clientp; mhd_handle_t *hp; /* default to local host */ if ((hostname == NULL) || (*hostname == '\0')) hostname = mynode(); /* open RPC connection */ assert(hostname != NULL); if ((clientp = meta_client_create(hostname, METAMHD, METAMHD_VERSION, "tcp")) == NULL) { clnt_pcreateerror(hostname); (void) mdrpccreateerror(ep, hostname, "metamhd clnt_create"); return (NULL); } else { auth_destroy(clientp->cl_auth); clientp->cl_auth = authsys_create_default(); assert(clientp->cl_auth != NULL); } /* return connection */ hp = Zalloc(sizeof (*hp)); hp->hostname = Strdup(hostname); hp->clientp = clientp; return (hp); }
/* * util_poolset_single -- (internal) create a one-part pool set * * On success returns a pointer to a newly allocated and initialized * pool set structure. Otherwise, NULL is returned. */ static struct pool_set * util_poolset_single(const char *path, size_t filesize, int fd, int create) { LOG(3, "path %s filesize %zu fd %d create %d", path, filesize, fd, create); struct pool_set *set; set = Zalloc(sizeof(struct pool_set) + sizeof(struct pool_replica *)); if (set == NULL) { ERR("!Malloc for pool set"); return NULL; } struct pool_replica *rep; rep = Zalloc(sizeof(struct pool_replica) + sizeof(struct pool_set_part)); if (rep == NULL) { ERR("!Malloc for pool set replica"); Free(set); return NULL; } set->replica[0] = rep; rep->part[0].filesize = filesize; rep->part[0].path = Strdup(path); rep->part[0].fd = fd; rep->part[0].created = create; rep->part[0].hdr = NULL; rep->part[0].addr = NULL; rep->nparts = 1; /* it does not have a remote replica */ rep->remote = NULL; set->remote = 0; /* round down to the nearest page boundary */ rep->repsize = rep->part[0].filesize & ~(Pagesize - 1); set->poolsize = rep->repsize; set->nreplicas = 1; return set; }
void list_alloc(list_t *list, int size) { if (size > 0) { list->l_size = size; list->l_ptrs = Zalloc(sizeof (void *) * (size + 1)); } }
void list_alloc(list_t *list, int size) { list->l_size = size; if (size > 0) list->l_ptrs = Zalloc(sizeof (void *) * (size + 1)); else list->l_ptrs = NULL; }
static lwp_info_t * list_add_lwp(list_t *list, pid_t pid, id_t lwpid) { lwp_info_t *lwp; if (list->l_head == NULL) { list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t)); } else { lwp = Zalloc(sizeof (lwp_info_t)); lwp->li_prev = list->l_tail; ((lwp_info_t *)list->l_tail)->li_next = lwp; list->l_tail = lwp; } lwp->li_info.pr_pid = pid; lwp->li_info.pr_lwp.pr_lwpid = lwpid; lwpid_add(lwp, pid, lwpid); list->l_count++; return (lwp); }
static int list_read(int listt, int elemn) { char idstr[P_MAXVAL]; list_t *list; id_info_t *id; if (listt == L_LWP) return (lwp_read(elemn)); while (elemn-- > 0) { switch (listt) { case L_PRC_SI : list = &processes; break; case L_USR_SI : list = &users; break; case L_PRJ_SI : list = &projects; break; } if (list->l_head == NULL) { /* first element */ list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t)); list->l_count++; } else { /* a new element */ id = list->l_tail; id->id_next = Zalloc(sizeof (id_info_t)); id->id_next->id_prev = list->l_tail; id->id_next->id_next = NULL; list->l_tail = id->id_next; id = list->l_tail; list->l_count++; } if (r_element((char *)id, idstr) == -1) { list_clear(list); return (-1); } } return (0); }
void lwpid_add(lwp_info_t *lwp, pid_t pid, id_t lwpid) { plwp_t *elm = Zalloc(sizeof (plwp_t)); int hash = pid % PLWP_TBL_SZ; elm->l_pid = pid; elm->l_lwpid = lwpid; elm->l_lwp = lwp; elm->l_next = plwp_tbl[hash]; /* add in front of chain */ plwp_tbl[hash] = elm; }
/* * status drives in set */ int mhd_status_drives( mhd_set_t *mhsp, mhd_opts_t options, mhd_drive_status_t **status, mhd_error_t *mhep ) { mhd_drive_list_t dl = mhd_null_list; mhd_drive_list_t *dlp = &dl; mhd_drive_set_t *sp; uint_t i; int rval = 0; /* grab global lock */ mhd_mx_lock(&mhd_set_mx); /* create or update set */ if ((sp = mhd_create_set(mhsp, options, &dl, mhep)) == NULL) { mhd_mx_unlock(&mhd_set_mx); mhd_free_list(&dl); return (-1); } /* lock set */ mhd_mx_lock(&sp->sr_mx); /* status drives */ if (mhd_status_set(sp, &dl, mhep) != 0) { rval = -1; goto out; } /* build list */ *status = Zalloc(dlp->dl_ndrive * sizeof (**status)); for (i = 0; (i < dlp->dl_ndrive); ++i) { mhd_drive_t *dp = dlp->dl_drives[i]; mhd_drive_status_t *statusp = &(*status)[i]; statusp->drive = Strdup(dp->dr_rname); statusp->errnum = dp->dr_errnum; } assert(i == dlp->dl_ndrive); rval = dlp->dl_ndrive; /* unlock, return count */ out: mhd_mx_unlock(&sp->sr_mx); mhd_mx_unlock(&mhd_set_mx); mhd_free_list(&dl); return (rval); }
/* * create_replica_health_status -- (internal) create helping structure for * storing replica's health status */ static struct replica_health_status * create_replica_health_status(struct pool_set *set, unsigned repn) { unsigned nparts = set->replica[repn]->nparts; struct replica_health_status *replica_hs; replica_hs = Zalloc(sizeof(struct replica_health_status) + nparts * sizeof(unsigned)); if (replica_hs == NULL) { ERR("!Zalloc for replica health status"); return NULL; } replica_hs->nparts = nparts; return replica_hs; }
/* * lane_boot -- initializes all lanes */ int lane_boot(PMEMobjpool *pop) { int err = 0; pop->lanes_desc.lane = Malloc(sizeof(struct lane) * pop->nlanes); if (pop->lanes_desc.lane == NULL) { err = ENOMEM; ERR("!Malloc of volatile lanes"); goto error_lanes_malloc; } pop->lanes_desc.next_lane_idx = 0; pop->lanes_desc.lane_locks = Zalloc(sizeof(*pop->lanes_desc.lane_locks) * pop->nlanes); if (pop->lanes_desc.lane_locks == NULL) { ERR("!Malloc for lane locks"); goto error_locks_malloc; } /* add lanes to pmemcheck ignored list */ VALGRIND_ADD_TO_GLOBAL_TX_IGNORE((char *)pop + pop->lanes_offset, (sizeof(struct lane_layout) * pop->nlanes)); uint64_t i; for (i = 0; i < pop->nlanes; ++i) { struct lane_layout *layout = lane_get_layout(pop, i); if ((err = lane_init(pop, &pop->lanes_desc.lane[i], layout))) { ERR("!lane_init"); goto error_lane_init; } } return 0; error_lane_init: for (; i >= 1; --i) lane_destroy(pop, &pop->lanes_desc.lane[i - 1]); Free(pop->lanes_desc.lane_locks); pop->lanes_desc.lane_locks = NULL; error_locks_malloc: Free(pop->lanes_desc.lane); pop->lanes_desc.lane = NULL; error_lanes_malloc: return err; }
/* * Add a device/device id tuple to the devname cache */ static void add_to_devname_list( char *device_name, /* fully qualified dev name */ ddi_devid_t devid /* device id */ ) { dev_list_t *dnlp; dnlp = Zalloc(sizeof (*dnlp)); dnlp->dev_name = Strdup(device_name); dnlp->devid = devid; /* link the node into the devname list */ dnlp->dev_nxt = devnamelist; devnamelist = dnlp; }
/* * shutdown_state_add_part -- adds file uuid and usc to shutdown_state struct * * if path does not exist it will fail which does NOT mean shutdown failure */ int shutdown_state_add_part(struct shutdown_state *sds, const char *path, struct pool_replica *rep) { LOG(3, "sds %p, path %s", sds, path); size_t len = 0; char *uid; uint64_t usc; if (os_dimm_usc(path, &usc)) { ERR("cannot read unsafe shutdown count of %s", path); return 1; } if (os_dimm_uid(path, NULL, &len)) { ERR("cannot read uuid of %s", path); return 1; } len += 4 - len % 4; uid = Zalloc(len); if (uid == NULL) { ERR("!Zalloc"); return 1; } if (os_dimm_uid(path, uid, &len)) { ERR("cannot read uuid of %s", path); Free(uid); return 1; } sds->usc = htole64(le64toh(sds->usc) + usc); uint64_t tmp; util_checksum(uid, len, &tmp, 1, 0); sds->uuid = htole64(le64toh(sds->uuid) + tmp); FLUSH_SDS(sds, rep); Free(uid); shutdown_state_checksum(sds, rep); return 0; }
/* * calloc */ void * Calloc( size_t n, size_t s ) { unsigned long total; if (n == 0 || s == 0) { total = 0; } else { total = (unsigned long)n * s; /* check for overflow */ if (total / n != s) return (NULL); } return (Zalloc(total)); }
/* * create poolset_compare_status -- (internal) create structure for gathering * status of poolset comparison */ static int create_poolset_compare_status(struct pool_set *set, struct poolset_compare_status **set_sp) { LOG(3, "set %p, set_sp %p", set, set_sp); struct poolset_compare_status *set_s; set_s = Zalloc(sizeof(struct poolset_compare_status) + set->nreplicas * sizeof(unsigned)); if (set_s == NULL) { ERR("!Zalloc for poolset status"); return -1; } for (unsigned r = 0; r < set->nreplicas; ++r) set_s->replica[r] = UNDEF_REPLICA; set_s->nreplicas = set->nreplicas; *set_sp = set_s; return 0; }
int os_execv(const char *path, char *const argv[]) { wchar_t *wpath = util_toUTF16(path); if (wpath == NULL) return -1; int argc = 0; while (argv[argc]) argc++; int ret; wchar_t **wargv = Zalloc((argc + 1) * sizeof(wargv[0])); if (!wargv) { ret = -1; goto wargv_alloc_failed; } for (int i = 0; i < argc; ++i) { wargv[i] = util_toUTF16(argv[i]); if (!wargv[i]) { ret = -1; goto end; } } intptr_t iret = _wexecv(wpath, wargv); if (iret == 0) ret = 0; else ret = -1; end: for (int i = 0; i < argc; ++i) util_free_UTF16(wargv[i]); Free(wargv); wargv_alloc_failed: util_free_UTF16(wpath); return ret; }
/* * build disk status list from drivename list */ md_disk_status_list_t * meta_drive_to_disk_status_list( mddrivenamelist_t *dnlp ) { md_disk_status_list_t *head = NULL; md_disk_status_list_t **tailp = &head; mddrivenamelist_t *p; /* copy list */ for (p = dnlp; (p != NULL); p = p->next) { md_disk_status_list_t *dsp; dsp = *tailp = Zalloc(sizeof (*dsp)); tailp = &dsp->next; dsp->drivenamep = p->drivenamep; } /* return list */ return (head); }
static void setmovecur() { int i, n; if ((opts.o_outpmode & OPT_FULLSCREEN) && (opts.o_outpmode & OPT_USEHOME)) { movecur = t_home; return; } if (opts.o_outpmode & OPT_SPLIT) { n = opts.o_ntop + opts.o_nbottom + 2; } else { if (opts.o_outpmode & OPT_USERS) n = opts.o_nbottom + 1; else n = opts.o_ntop + 1; } if (movecur != NULL && movecur != empty_string && movecur != t_home) free(movecur); movecur = Zalloc(strlen(t_up) * (n + 5)); for (i = 0; i <= n; i++) (void) strcat(movecur, t_up); }
/* * util_poolset_parse -- (internal) parse pool set config file * * Returns 1 if the file is a valid pool set config file, 0 if the file * is not a pool set header, and -1 in case of any error. * * XXX: use memory mapped file */ int util_poolset_parse(const char *path, int fd, struct pool_set **setp) { LOG(3, "path %s fd %d setp %p", path, fd, setp); struct pool_set *set; enum parser_codes result; char line[PARSER_MAX_LINE]; char *s; char *ppath; char *pool_desc; char *node_addr; char *cp; size_t psize; FILE *fs; if (util_lseek(fd, 0, SEEK_SET) != 0) { ERR("!lseek %d", fd); return -1; } fd = dup(fd); if (fd < 0) { ERR("!dup"); return -1; } /* associate a stream with the file descriptor */ if ((fs = fdopen(fd, "r")) == NULL) { ERR("!fdopen %d", fd); close(fd); return -1; } unsigned nlines = 0; unsigned nparts = 0; /* number of parts in current replica */ /* read the first line */ s = fgets(line, PARSER_MAX_LINE, fs); nlines++; set = Zalloc(sizeof(struct pool_set)); if (set == NULL) { ERR("!Malloc for pool set"); goto err; } /* check also if the last character is '\n' */ if (s && strncmp(line, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN) == 0 && line[POOLSET_HDR_SIG_LEN] == '\n') { /* 'PMEMPOOLSET' signature detected */ LOG(10, "PMEMPOOLSET"); int ret = util_parse_add_replica(&set); if (ret != 0) goto err; nparts = 0; result = PARSER_CONTINUE; } else { result = PARSER_PMEMPOOLSET; } while (result == PARSER_CONTINUE) { /* read next line */ s = fgets(line, PARSER_MAX_LINE, fs); nlines++; if (s) { /* chop off newline and comments */ if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; if (cp != s && (cp = strchr(line, '#')) != NULL) *cp = '\0'; /* skip comments and blank lines */ if (cp == s) continue; } if (!s) { if (nparts >= 1) { result = PARSER_FORMAT_OK; } else { if (set->nreplicas == 1) result = PARSER_SET_NO_PARTS; else result = PARSER_REP_NO_PARTS; } } else if (strncmp(line, POOLSET_REPLICA_SIG, POOLSET_REPLICA_SIG_LEN) == 0) { if (line[POOLSET_REPLICA_SIG_LEN] != '\0') { /* something more than 'REPLICA' */ if (!isblank(line[POOLSET_REPLICA_SIG_LEN])) { result = PARSER_REPLICA; continue; } /* check if it is a remote replica */ result = parser_read_replica( line + POOLSET_REPLICA_SIG_LEN, &node_addr, &pool_desc); if (result == PARSER_CONTINUE) { /* remote REPLICA */ LOG(10, "REMOTE REPLICA " "node address '%s' " "pool set descriptor '%s'", node_addr, pool_desc); if (util_parse_add_remote_replica(&set, node_addr, pool_desc)) goto err; } } else if (nparts >= 1) { /* 'REPLICA' signature detected */ LOG(10, "REPLICA"); int ret = util_parse_add_replica(&set); if (ret != 0) goto err; nparts = 0; result = PARSER_CONTINUE; } else { if (set->nreplicas == 1) result = PARSER_SET_NO_PARTS; else result = PARSER_REP_NO_PARTS; } } else { /* read size and path */ result = parser_read_line(line, &psize, &ppath); if (result == PARSER_CONTINUE) { /* add a new pool's part to the list */ int ret = util_parse_add_part(set, ppath, psize); if (ret != 0) goto err; nparts++; } } } if (result == PARSER_FORMAT_OK) { LOG(4, "set file format correct (%s)", path); (void) fclose(fs); util_poolset_set_size(set); *setp = set; return 0; } else { ERR("%s [%s:%d]", path, parser_errstr[result], nlines); errno = EINVAL; } err: (void) fclose(fs); if (set) util_poolset_free(set); return -1; }
/* * alloc_class_collection_new -- creates a new collection of allocation classes */ struct alloc_class_collection * alloc_class_collection_new() { LOG(10, NULL); struct alloc_class_collection *ac = Zalloc(sizeof(*ac)); if (ac == NULL) return NULL; memset(ac->aclasses, 0, sizeof(ac->aclasses)); ac->granularity = ALLOC_BLOCK_SIZE; ac->last_run_max_size = MAX_RUN_SIZE; ac->fail_on_missing_class = 0; ac->autogenerate_on_missing_class = 1; size_t maps_size = (MAX_RUN_SIZE / ac->granularity) + 1; if ((ac->class_map_by_alloc_size = Malloc(maps_size)) == NULL) goto error; if ((ac->class_map_by_unit_size = cuckoo_new()) == NULL) goto error; memset(ac->class_map_by_alloc_size, 0xFF, maps_size); if (alloc_class_new(-1, ac, CLASS_HUGE, HEADER_COMPACT, CHUNKSIZE, 0, 1) == NULL) goto error; struct alloc_class *predefined_class = alloc_class_new(-1, ac, CLASS_RUN, HEADER_COMPACT, MIN_RUN_SIZE, 0, 1); if (predefined_class == NULL) goto error; for (size_t i = 0; i < FIRST_GENERATED_CLASS_SIZE / ac->granularity; ++i) { ac->class_map_by_alloc_size[i] = predefined_class->id; } /* * Based on the defined categories, a set of allocation classes is * created. The unit size of those classes is depended on the category * initial size and step. */ size_t granularity_mask = ALLOC_BLOCK_SIZE_GEN - 1; for (int c = 1; c < MAX_ALLOC_CATEGORIES; ++c) { size_t n = categories[c - 1].size + ALLOC_BLOCK_SIZE_GEN; do { if (alloc_class_find_or_create(ac, n) == NULL) goto error; float stepf = (float)n * categories[c].step; size_t stepi = (size_t)stepf; stepi = (stepf - (float)stepi < FLT_EPSILON) ? stepi : stepi + 1; n += (stepi + (granularity_mask)) & ~granularity_mask; } while (n <= categories[c].size); } /* * Find the largest alloc class and use it's unit size as run allocation * threshold. */ uint8_t largest_aclass_slot; for (largest_aclass_slot = MAX_ALLOCATION_CLASSES - 1; largest_aclass_slot > 0 && ac->aclasses[largest_aclass_slot] == NULL; --largest_aclass_slot) { /* intentional NOP */ } struct alloc_class *c = ac->aclasses[largest_aclass_slot]; /* * The actual run might contain less unit blocks than the theoretical * unit max variable. This may be the case for very large unit sizes. */ size_t real_unit_max = c->run.bitmap_nallocs < RUN_UNIT_MAX_ALLOC ? c->run.bitmap_nallocs : RUN_UNIT_MAX_ALLOC; size_t theoretical_run_max_size = c->unit_size * real_unit_max; ac->last_run_max_size = MAX_RUN_SIZE > theoretical_run_max_size ? theoretical_run_max_size : MAX_RUN_SIZE; #ifdef DEBUG /* * Verify that each bucket's unit size points back to the bucket by the * bucket map. This must be true for the default allocation classes, * otherwise duplicate buckets will be created. */ for (size_t i = 0; i < MAX_ALLOCATION_CLASSES; ++i) { struct alloc_class *c = ac->aclasses[i]; if (c != NULL && c->type == CLASS_RUN) { ASSERTeq(i, c->id); ASSERTeq(alloc_class_by_run(ac, c->unit_size, c->flags, c->run.size_idx), c); } } #endif return ac; error: alloc_class_collection_delete(ac); return NULL; }
/* * FUNCTION: meta_replicaslice() * INPUT: dnp - the name of the drive to check * OUTPUT: slicep - pointer to slice number * ep - pointer to an md_error_t structure in which * to return errors to the caller * RETURNS: int - 0 - value pointed to by slicep is valid * -1 - otherwise * * PURPOSE: Determine which slice of the specified drive to * reserve, presumably for metadb replica usage. * * NOTE: If slicep is NULL, the return code will indicate * whether or not the slice number could be determined */ int meta_replicaslice( mddrivename_t *dnp, uint_t *slicep, md_error_t *ep ) { int err = 0; int ioctl_return; int fd; char *rname; struct dk_geom geom; rname = dnp->rname; if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) { char *n; int open_errno; size_t len; if (errno != ENOENT) return (mdsyserror(ep, errno, rname)); len = strlen(rname) + 3; n = Zalloc(len); (void) snprintf(n, len, "%ss0", rname); fd = open(n, (O_RDONLY|O_NDELAY), 0); open_errno = errno; Free(n); if (fd < 0) { return (mdsyserror(ep, open_errno, rname)); } } /* * if our drivenamep points to a device not supporting * DKIOCGGEOM, we have an EFI label. */ errno = 0; ioctl_return = ioctl(fd, DKIOCGGEOM, &geom); err = errno; (void) close(fd); /* * If the DKIOCGGEOM ioctl succeeded, then the device has a * VTOC style label. In this case, we use slice 7. */ if (ioctl_return == 0) { if (slicep != NULL) { *slicep = MD_SLICE7; } return (0); } /* * ENOTSUP indicates an EFI style label, in which case slice 7 * cannot be used because its minor number is reserved. In * this case, use slice 6. */ if (err == ENOTSUP) { if (slicep != NULL) { *slicep = MD_SLICE6; } return (0); } /* * Those are the only two cases we know how to deal with; * either the drivenamep didn't point to a disk, or the ioctl * failed for some other reason. */ if (err == ENOTTY) { return (mddeverror(ep, MDE_NOT_DISK, NODEV, rname)); } return (mdsyserror(ep, err, rname)); }
/* * os_badblocks_get -- returns 0 and bad blocks in the 'bbs' array * (that has to be pre-allocated) * or -1 in case of an error */ int os_badblocks_get(const char *file, struct badblocks *bbs) { LOG(3, "file %s badblocks %p", file, bbs); ASSERTne(bbs, NULL); VEC(bbsvec, struct bad_block) bbv = VEC_INITIALIZER; struct extents *exts = NULL; long extents = 0; unsigned long long bb_beg; unsigned long long bb_end; unsigned long long bb_len; unsigned long long bb_off; unsigned long long ext_beg; unsigned long long ext_end; unsigned long long not_block_aligned; int bb_found = -1; /* -1 means an error */ memset(bbs, 0, sizeof(*bbs)); if (os_dimm_files_namespace_badblocks(file, bbs)) { LOG(1, "checking the file for bad blocks failed -- '%s'", file); goto error_free_all; } if (bbs->bb_cnt == 0) { bb_found = 0; goto exit_free_all; } exts = Zalloc(sizeof(struct extents)); if (exts == NULL) { ERR("!Zalloc"); goto error_free_all; } extents = os_extents_count(file, exts); if (extents < 0) { LOG(1, "counting file's extents failed -- '%s'", file); goto error_free_all; } if (extents == 0) { /* dax device has no extents */ bb_found = (int)bbs->bb_cnt; for (unsigned b = 0; b < bbs->bb_cnt; b++) { LOG(4, "bad block found: offset: %llu, length: %u", bbs->bbv[b].offset, bbs->bbv[b].length); } goto exit_free_all; } exts->extents = Zalloc(exts->extents_count * sizeof(struct extent)); if (exts->extents == NULL) { ERR("!Zalloc"); goto error_free_all; } if (os_extents_get(file, exts)) { LOG(1, "getting file's extents failed -- '%s'", file); goto error_free_all; } bb_found = 0; for (unsigned b = 0; b < bbs->bb_cnt; b++) { bb_beg = bbs->bbv[b].offset; bb_end = bb_beg + bbs->bbv[b].length - 1; for (unsigned e = 0; e < exts->extents_count; e++) { ext_beg = exts->extents[e].offset_physical; ext_end = ext_beg + exts->extents[e].length - 1; /* check if the bad block overlaps with file's extent */ if (bb_beg > ext_end || ext_beg > bb_end) continue; bb_found++; bb_beg = (bb_beg > ext_beg) ? bb_beg : ext_beg; bb_end = (bb_end < ext_end) ? bb_end : ext_end; bb_len = bb_end - bb_beg + 1; bb_off = bb_beg + exts->extents[e].offset_logical - exts->extents[e].offset_physical; LOG(10, "bad block found: physical offset: %llu, length: %llu", bb_beg, bb_len); /* check if offset is block-aligned */ not_block_aligned = bb_off & (exts->blksize - 1); if (not_block_aligned) { bb_off -= not_block_aligned; bb_len += not_block_aligned; } /* check if length is block-aligned */ bb_len = ALIGN_UP(bb_len, exts->blksize); LOG(4, "bad block found: logical offset: %llu, length: %llu", bb_off, bb_len); /* * Form a new bad block structure with offset and length * expressed in bytes and offset relative * to the beginning of the file. */ struct bad_block bb; bb.offset = bb_off; bb.length = (unsigned)(bb_len); /* unknown healthy replica */ bb.nhealthy = NO_HEALTHY_REPLICA; /* add the new bad block to the vector */ if (VEC_PUSH_BACK(&bbv, bb)) { VEC_DELETE(&bbv); bb_found = -1; goto error_free_all; } } } error_free_all: Free(bbs->bbv); bbs->bbv = NULL; bbs->bb_cnt = 0; exit_free_all: if (exts) { Free(exts->extents); Free(exts); } if (extents > 0 && bb_found > 0) { bbs->bbv = VEC_ARR(&bbv); bbs->bb_cnt = (unsigned)VEC_SIZE(&bbv); LOG(10, "number of bad blocks detected: %u", bbs->bb_cnt); /* sanity check */ ASSERTeq((unsigned)bb_found, bbs->bb_cnt); } return (bb_found >= 0) ? 0 : -1; }
/* * list all the drives */ int mhd_list_drives( char *path, mhd_did_flags_t flags, mhd_list_res_t *resultsp, mhd_error_t *mhep ) { mhd_state_t state; uint_t ndrive, i, j, c; /* grab lock */ mhd_mx_lock(&mhd_set_mx); /* add path to list */ if (mhd_create_drives(path, mhep) != 0) { mhd_mx_unlock(&mhd_set_mx); return (-1); } /* get what we want */ state = 0; if (flags & MHD_DID_SERIAL) state |= DRIVE_SERIALING; if (flags & MHD_DID_TIME) state |= DRIVE_VTOCING; if (flags & MHD_DID_CINFO) state |= DRIVE_CINFOING; /* ident and count drives */ for (ndrive = 0, i = 0; (i < mhd_nset); ++i) { mhd_drive_set_t *sp = mhd_sets[i]; mhd_drive_list_t *dlp = &sp->sr_drives; /* count drives */ ndrive += dlp->dl_ndrive; /* ident drives */ if (state != 0) { mhd_mx_lock(&sp->sr_mx); for (j = 0; (j < dlp->dl_ndrive); ++j) { mhd_drive_t *dp = dlp->dl_drives[j]; if (mhd_state_set(dp, state, mhep) != 0) { mhd_mx_unlock(&sp->sr_mx); mhd_mx_unlock(&mhd_set_mx); return (-1); } } mhd_wait_set(sp, dlp, state); mhd_mx_unlock(&sp->sr_mx); } } /* build list */ assert(resultsp->results.mhd_drive_info_list_t_len == 0); assert(resultsp->results.mhd_drive_info_list_t_val == NULL); resultsp->results.mhd_drive_info_list_t_len = ndrive; resultsp->results.mhd_drive_info_list_t_val = Zalloc( ndrive * sizeof (*resultsp->results.mhd_drive_info_list_t_val)); for (c = 0, i = 0; (i < mhd_nset); ++i) { mhd_drive_set_t *sp = mhd_sets[i]; mhd_drive_list_t *dlp = &sp->sr_drives; mhd_mx_lock(&sp->sr_mx); for (j = 0; (j < dlp->dl_ndrive); ++j) { mhd_drive_t *dp = dlp->dl_drives[j]; mhd_drive_info_t *ip = &resultsp->results.mhd_drive_info_list_t_val[c++]; ip->dif_name = Strdup(dp->dr_rname); ip->dif_id = dp->dr_drive_id; } mhd_mx_unlock(&sp->sr_mx); } assert(c == ndrive); /* unlock, return count */ mhd_mx_unlock(&mhd_set_mx); return (ndrive); }
/* * create or update new set */ mhd_drive_set_t * mhd_create_set( mhd_set_t *mhsp, mhd_opts_t options, mhd_drive_list_t *dlp, mhd_error_t *mhep ) { char *setname; mhd_drive_set_t *sp; mhd_drive_list_t *sp_dlp; mhd_drive_set_t *null_sp; uint_t i; /* check locks */ assert(MUTEX_HELD(&mhd_set_mx)); /* get setname */ if (mhsp == NULL) setname = ""; else setname = mhsp->setname; /* find or create set */ if ((sp = mhd_find_set(setname)) == NULL) { /* allocate and initialize set */ sp = Zalloc(sizeof (*sp)); sp->sr_name = Strdup(setname); mhd_mx_init(&sp->sr_mx); mhd_cv_init(&sp->sr_cv); sp->sr_ff = -1; /* append to set list */ ++mhd_nset; mhd_sets = Realloc(mhd_sets, (mhd_nset * sizeof (*mhd_sets))); mhd_sets[mhd_nset - 1] = sp; } sp_dlp = &sp->sr_drives; /* if just grabbing null set, return */ if (mhsp == NULL) return (sp); assert(strcmp(setname, "") != 0); assert(mhep != NULL); /* get null set */ null_sp = mhd_create_set(NULL, 0, NULL, NULL); assert(null_sp != NULL); assert(sp != null_sp); /* grab set lock */ mhd_mx_lock(&sp->sr_mx); /* save options */ if (options & MHD_SERIAL) sp->sr_options |= MHD_SERIAL; else sp->sr_options &= ~MHD_SERIAL; /* move drives no longer in set to null set */ if (! (options & MHD_PARTIAL_SET)) { for (i = 0; (i < sp_dlp->dl_ndrive); /* void */) { mhd_drive_t *dp = sp_dlp->dl_drives[i]; uint_t j; /* check still there */ for (j = 0; (j < mhsp->drives.drives_len); ++j) { mhd_drivename_t mhdp; mhdp = mhsp->drives.drives_val[j]; if (strcmp(dp->dr_rname, mhdp) == 0) break; } if (j < mhsp->drives.drives_len) { ++i; continue; } /* idle the drive */ if (mhd_idle(dp, mhep) != 0) mhd_clrerror(mhep); /* move to null set */ mhd_del_drive_from_set(dp); mhd_mx_unlock(&sp->sr_mx); mhd_mx_lock(&null_sp->sr_mx); mhd_add_drive_to_set(null_sp, dp); mhd_mx_unlock(&null_sp->sr_mx); mhd_mx_lock(&sp->sr_mx); } } /* add new drives to lists */ for (i = 0; (i < mhsp->drives.drives_len); ++i) { mhd_drivename_t mhdp = mhsp->drives.drives_val[i]; uint_t j; mhd_drive_t *dp; /* check already there */ for (j = 0; (j < dlp->dl_ndrive); ++j) { dp = dlp->dl_drives[j]; if (strcmp(mhdp, dp->dr_rname) == 0) break; } if (j < dlp->dl_ndrive) { mhd_add_drive(dlp, dp); continue; } /* add drive to set */ if ((dp = mhd_create_drive(sp, mhdp, NULL, mhep)) == NULL) { mhde_perror(mhep, "mhd_create_drive: %s", mhdp); continue; } mhd_add_drive(dlp, dp); } /* debug */ #ifdef MHD_DEBUG if (mhd_debug > 0) { for (i = 0; (i < mhd_nset); ++i) { mhd_drive_set_t *sp = mhd_sets[i]; mhd_drive_list_t *dlp = &sp->sr_drives; char buf[10240]; uint_t j; (void) snprintf(buf, sizeof (buf), "set '%s':", sp->sr_name); for (j = 0; (j < dlp->dl_ndrive); ++j) { mhd_drive_t *dp = dlp->dl_drives[j]; char *p; if ((p = strrchr(dp->dr_rname, '/')) != NULL) ++p; else p = dp->dr_rname; (void) strncat(buf, " ", sizeof (buf)); (void) strncat(buf, p, sizeof (buf)); } buf[sizeof (buf) - 1] = '\0'; mhd_eprintf("%s\n", buf); } } #endif /* MHD_DEBUG */ /* unlock, return set */ mhd_mx_unlock(&sp->sr_mx); return (sp); }
static void list_update(list_t *list, lwp_info_t *lwp) { id_info_t *id; if (list->l_head == NULL) { /* first element */ list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t)); goto update; } for (id = list->l_head; id; id = id->id_next) { if ((list->l_type == LT_USERS) && (id->id_uid != lwp->li_info.pr_uid)) continue; if ((list->l_type == LT_TASKS) && (id->id_taskid != lwp->li_info.pr_taskid)) continue; if ((list->l_type == LT_PROJECTS) && (id->id_projid != lwp->li_info.pr_projid)) continue; if ((list->l_type == LT_ZONES) && (id->id_zoneid != lwp->li_info.pr_zoneid)) continue; id->id_nproc++; id->id_taskid = lwp->li_info.pr_taskid; id->id_projid = lwp->li_info.pr_projid; id->id_zoneid = lwp->li_info.pr_zoneid; if (lwp->li_flags & LWP_REPRESENT) { id->id_size += lwp->li_info.pr_size; id->id_rssize += lwp->li_info.pr_rssize; } id->id_pctcpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); if (opts.o_outpmode & OPT_LWPS) id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time); else id->id_time += TIME2SEC(lwp->li_info.pr_time); id->id_pctmem += FRC2PCT(lwp->li_info.pr_pctmem); id->id_key += lwp->li_key; total_cpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); total_mem += FRC2PCT(lwp->li_info.pr_pctmem); return; } id = list->l_tail; id->id_next = Zalloc(sizeof (id_info_t)); id->id_next->id_prev = list->l_tail; id->id_next->id_next = NULL; list->l_tail = id->id_next; id = list->l_tail; update: id->id_uid = lwp->li_info.pr_uid; id->id_projid = lwp->li_info.pr_projid; id->id_taskid = lwp->li_info.pr_taskid; id->id_zoneid = lwp->li_info.pr_zoneid; id->id_nproc++; if (lwp->li_flags & LWP_REPRESENT) { id->id_size = lwp->li_info.pr_size; id->id_rssize = lwp->li_info.pr_rssize; } id->id_pctcpu = FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); if (opts.o_outpmode & OPT_LWPS) id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time); else id->id_time = TIME2SEC(lwp->li_info.pr_time); id->id_pctmem = FRC2PCT(lwp->li_info.pr_pctmem); id->id_key = lwp->li_key; total_cpu += id->id_pctcpu; total_mem += id->id_pctmem; list->l_count++; }