/* * Pull POSIX ACLs from an fcmh via RPCs to MDS. */ acl_t slc_acl_get_fcmh(struct pscfs_req *pfr, const struct pscfs_creds *pcr, struct fidc_membh *f) { char trybuf[64] = { 0 }; void *buf = NULL; size_t retsz = 0; ssize_t rc; acl_t a; rc = slc_getxattr(pfr, pcr, ACL_EA_ACCESS, trybuf, sizeof(trybuf), f, &retsz); if (rc == 0) { buf = trybuf; } else if (rc == ERANGE) { buf = PSCALLOC(retsz); rc = slc_getxattr(pfr, pcr, ACL_EA_ACCESS, buf, retsz, f, &retsz); if (rc) { PSCFREE(buf); return (NULL); } } else return (NULL); a = pfl_acl_from_xattr(buf, retsz); if (buf != trybuf) PSCFREE(buf); return (a); }
void mod_destroy(struct wok_module *wm) { dlclose(wm->wm_handle); PSCFREE(wm->wm_path); PSCFREE(wm); }
struct wok_module * mod_load(const char *path, const char *opts, char *errbuf, size_t errlen) { int (*loadf)(struct pscfs *); struct wok_module *wm; void *h; int rc; h = dlopen(path, RTLD_NOW); if (h == NULL) { snprintf(errbuf, LINE_MAX, "%s\n", dlerror()); fprintf(stderr, errbuf); return (NULL); } loadf = dlsym(h, "pscfs_module_load"); if (loadf == NULL) { dlclose(h); snprintf(errbuf, LINE_MAX, "symbol pscfs_module_load undefined.\n"); fprintf(stderr, errbuf); return (NULL); } wm = PSCALLOC(sizeof(*wm)); wm->wm_path = pfl_strdup(path); wm->wm_handle = h; wm->wm_opts = pfl_strdup(opts); wm->wm_module.pf_private = wm; pflfs_module_init(&wm->wm_module, opts); rc = loadf(&wm->wm_module); /* * XXX XXX XXX * This is a complete hack but this flush somehow avoids a bunch * of zeroes from ending up in the log... * XXX XXX XXX */ fflush(stderr); if (rc) { wm->wm_module.pf_handle_destroy = NULL; pflfs_module_destroy(&wm->wm_module); dlclose(h); PSCFREE(wm->wm_path); PSCFREE(wm); psclog_warnx("module failed to load: rc=%d module=%s", rc, path); strlcpy(errbuf, strerror(rc), errlen); return (NULL); } return (wm); }
void pfl_odt_release(struct pfl_odt *t) { if (t->odt_bitmap) psc_vbitmap_free(t->odt_bitmap); t->odt_ops.odtop_close(t); pfl_opstat_destroy(t->odt_iostats.rd); pfl_opstat_destroy(t->odt_iostats.wr); PSCFREE(t->odt_hdr); PSCFREE(t); }
void pfl_odt_check(struct pfl_odt *t, void (*cbf)(void *, int64_t, void *), void *arg) { struct pfl_odt_slotftr *f; struct pfl_odt_hdr *h; struct pfl_meter mtr; uint64_t crc; void *p; h = t->odt_hdr; pfl_meter_init(&mtr, 0, "odt-%s", t->odt_name); mtr.pm_max = h->odth_nitems; #define i mtr.pm_cur for (i = 0; i < h->odth_nitems; i++) { pfl_odt_getslot(t, i, &p, &f); if (f->odtf_slotno != i) PFLOG_ODT(PLL_FATAL, t, "footercheck: i=%"PRIu64, i); if (h->odth_options & ODTBL_OPT_CRC) { psc_crc64_init(&crc); if (f->odtf_flags & ODT_FTRF_INUSE) psc_crc64_add(&crc, p, h->odth_itemsz); psc_crc64_add(&crc, f, sizeof(*f) - sizeof(f->odtf_crc)); psc_crc64_fini(&crc); if (crc != f->odtf_crc) PFLOG_ODT(PLL_FATAL, t, "CRC failed; slot=%"PRId64" " "mem_crc=%"PSCPRIxCRC64" " "ftr_crc=%"PSCPRIxCRC64, i, crc, f->odtf_crc); } if (f->odtf_flags & ODT_FTRF_INUSE) { psc_vbitmap_set(t->odt_bitmap, i); if (cbf) cbf(p, i, arg); } PSCFREE(p); PSCFREE(f); } #undef i pfl_meter_destroy(&mtr); }
void slm_fcmh_dtor(struct fidc_membh *f) { struct fcmh_mds_info *fmi; int rc, vfsid; fmi = fcmh_2_fmi(f); if (fcmh_isreg(f)) { psc_assert(psc_dynarray_len(&fmi->fmi_ptrunc_clients) == 0); psc_dynarray_free(&fmi->fmi_ptrunc_clients); } if (fcmh_isreg(f) || fcmh_isdir(f)) { /* XXX Need to worry about other modes here */ if (!fmi->fmi_ctor_rc) { slfid_to_vfsid(fcmh_2_fid(f), &vfsid); rc = mdsio_release(vfsid, &rootcreds, fcmh_2_mfh(f)); psc_assert(rc == 0); } } if (fcmh_isdir(f)) { slfid_to_vfsid(fcmh_2_fid(f), &vfsid); rc = mdsio_release(vfsid, &rootcreds, fcmh_2_dino_mfh(f)); psc_assert(rc == 0); } if (fmi->fmi_inodeh.inoh_extras) PSCFREE(fmi->fmi_inodeh.inoh_extras); }
/* * Handle a NAMESPACE_UPDATE request from another MDS. */ int slm_rmm_handle_namespace_update(struct pscrpc_request *rq) { struct srt_update_entry *entryp; struct srm_update_req *mq; struct srm_update_rep *mp; struct sl_mds_peerinfo *p; struct sl_resource *res; struct sl_site *site; struct iovec iov; int i, len, count; SL_RSX_ALLOCREP(rq, mq, mp); count = mq->count; if (count <= 0 || mq->size > LNET_MTU) { mp->rc = -EINVAL; return (mp->rc); } iov.iov_len = mq->size; iov.iov_base = PSCALLOC(mq->size); mp->rc = slrpc_bulkserver(rq, BULK_GET_SINK, SRMM_BULK_PORTAL, &iov, 1); if (mp->rc) goto out; /* Search for the peer information by the given site ID. */ site = libsl_siteid2site(mq->siteid); p = NULL; if (site) SITE_FOREACH_RES(site, res, i) if (res->res_type == SLREST_MDS) { p = res2rpmi(res)->rpmi_info; break; } if (p == NULL) { psclog_info("fail to find site ID %d", mq->siteid); PFL_GOTOERR(out, mp->rc = -EINVAL); } /* * Iterate through the namespace update buffer and apply updates. * If we fail to apply an update, we still report success to our * peer because reporting an error does not help our cause. */ entryp = iov.iov_base; for (i = 0; i < count; i++) { slm_rmm_apply_update(entryp); len = UPDATE_ENTRY_LEN(entryp); entryp = PSC_AGP(entryp, len); } zfsslash2_wait_synced(0); out: PSCFREE(iov.iov_base); return (mp->rc); }
/** * pflnet_freeifaddrs - Release network interface addresses. * @ifa: addresses to free. */ void pflnet_freeifaddrs(struct ifaddrs *ifa) { #ifdef HAVE_GETIFADDRS freeifaddrs(ifa); #else PSCFREE(ifa); #endif }
void pfl_opstat_destroy_pos(int pos) { struct pfl_opstat *opst; LOCK_ENSURE(&pfl_opstats_lock); opst = psc_dynarray_getpos(&pfl_opstats, pos); psc_dynarray_splice(&pfl_opstats, pos, 1, NULL, 0); PSCFREE(opst); }
void pfl_opstats_grad_destroy(struct pfl_opstats_grad *og) { struct pfl_opstat_bucket *ob; int i; for (i = 0, ob = og->og_buckets; i < og->og_nbuckets; i++, ob++) pfl_opstat_destroy(ob->ob_opst); PSCFREE(og->og_buckets); }
int main(int argc, char *argv[]) { size_t sz; void *p; pfl_init(); if (getopt(argc, argv, "") != -1) usage(); argc -= optind; if (argc) usage(); p = PSCALLOC(213); p = psc_realloc(p, 65536, 0); p = psc_realloc(p, 0, 0); p = psc_realloc(p, 128, 0); p = psc_realloc(p, 0, 0); PSCFREE(p); p = PSCALLOC(128); PSCFREE(p); p = psc_alloc(24, PAF_PAGEALIGN); psc_free(p, PAF_PAGEALIGN); p = PSCALLOC(24); p = psc_realloc(p, 128, 0); PSCFREE(p); p = psc_alloc(8, PAF_LOCK); *(uint64_t *)p = 0; psc_free(p, PAF_LOCK, (size_t)8); sz = 1024; p = psc_alloc(sz, PAF_LOCK | PAF_PAGEALIGN); memset(p, 0, sz); psc_free(p, PAF_LOCK | PAF_PAGEALIGN, sz); exit(0); }
__static int pflnet_rtexists_sysctl(const struct sockaddr *sa) { union { struct rt_msghdr *rtm; char *ch; void *p; } u; union pfl_sockaddr_ptr s, os; int rc = 0, mib[6]; char *buf = NULL; size_t len; os.cp = sa; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = AF_INET; mib[4] = NET_RT_DUMP; mib[5] = 0; /* no flags */ if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1) psc_fatal("route-sysctl-estimate"); if (len) { buf = PSCALLOC(len); if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) psc_fatal("actual retrieval of routing table"); } for (u.p = buf; u.ch && u.ch < buf + len; u.ch += u.rtm->rtm_msglen) { if (u.rtm->rtm_version != RTM_VERSION) continue; s.p = u.rtm + 1; if (s.s->sin.sin_addr.s_addr == os.s->sin.sin_addr.s_addr) { rc = 1; break; } } PSCFREE(buf); return (rc); }
/* * Traverse a file hierarchy and perform an operation on each file * system entry. * @fn: file root. * @flags: behavorial flags. * @cmpf: optional dirent comparator for ordering. * @cbf: callback to invoke on each file. * @arg: optional argument to supply to callback. * Notes: the callback will be invoked with a fully resolved absolute * path name unless the file in question is a symbolic link. */ int pfl_filewalk(const char *fn, int flags, void *cmpf, int (*cbf)(FTSENT *, void *), void *arg) { char * const pathv[] = { (char *)fn, NULL }; int rc = 0, f_flags = 0; struct stat stb; FTSENT *f; FTS *fp; if (flags & PFL_FILEWALKF_RECURSIVE) { if (flags & PFL_FILEWALKF_NOSTAT) f_flags |= FTS_NOSTAT; if (flags & PFL_FILEWALKF_NOCHDIR) f_flags |= FTS_NOCHDIR; fp = pfl_fts_open(pathv, f_flags | FTS_COMFOLLOW | FTS_PHYSICAL, cmpf); if (fp == NULL) psc_fatal("fts_open %s", fn); while ((f = pfl_fts_read(fp)) != NULL) { switch (f->fts_info) { case FTS_NS: psclog_warnx("%s: %s", f->fts_path, strerror(f->fts_errno)); break; case FTS_F: case FTS_D: case FTS_SL: if (flags & PFL_FILEWALKF_VERBOSE) warnx("processing %s%s", fn, f->fts_info == FTS_D ? "/" : ""); case FTS_DP: rc = cbf(f, arg); if (rc) { pfl_fts_close(fp); return (rc); } break; default: if (f->fts_errno == 0) f->fts_errno = EOPNOTSUPP; psclog_warnx("%s: %s", f->fts_path, strerror(f->fts_errno)); break; } } pfl_fts_close(fp); } else { const char *basefn; size_t baselen; if (lstat(fn, &stb) == -1) err(1, "%s", fn); basefn = pfl_basename(fn); baselen = strlen(basefn); f = PSCALLOC(sizeof(*f) + baselen); f->fts_accpath = (char *)fn; f->fts_path = (char *)fn; f->fts_pathlen = strlen(fn); strlcpy(f->fts_name, basefn, baselen + 1); f->fts_namelen = baselen; f->fts_ino = stb.st_ino; f->fts_statp = &stb; switch (stb.st_mode & S_IFMT) { case S_IFDIR: f->fts_info = FTS_D; break; case S_IFREG: f->fts_info = FTS_F; break; case S_IFLNK: f->fts_info = FTS_SL; break; case S_IFBLK: f->fts_info = FTS_DEFAULT; break; default: psclog_warnx("%s: %s", fn, strerror(EOPNOTSUPP)); break; } rc = cbf(f, arg); PSCFREE(f); } return (rc); }
/* * Free aligned memory. * @p: memory chunk to free. */ void psc_freen(void *p) { /* XXX recover original pointer value. */ PSCFREE(p); }
void slab_free(struct slab *slb) { PSCFREE(slb->slb_base); psc_pool_return(slab_pool, slb); }
int main(int argc, char *argv[]) { int c, i, rc, verbose = 0, oflg = ODTBL_FLG_RDONLY, tflg = ODTBL_OPT_CRC; struct pfl_odt *t; char *p, *fn; pfl_init(); pscthr_init(0, NULL, 0, "odtable"); while ((c = getopt(argc, argv, "CcdF:n:osvX:z:")) != -1) switch (c) { case 'C': create_table = 1; break; case 'c': tflg |= ODTBL_OPT_CRC; break; case 'd': dump = 1; break; case 'F': num_free = atoi(optarg); oflg &= ~ODTBL_FLG_RDONLY; break; case 'n': num_puts = atoi(optarg); oflg &= ~ODTBL_FLG_RDONLY; break; case 'o': overwrite = 1; break; case 's': item_size = atoi(optarg); break; case 'v': verbose = 1; break; case 'X': fmt = optarg; break; case 'z': nitems = atoi(optarg); break; default: usage(); } argc -= optind; argv += optind; if (argc != 1) usage(); fn = argv[0]; if (create_table) { rc = pfl_odt_create(fn, nitems, item_size, overwrite, ODT_ITEM_START, 0, tflg); if (!rc && verbose) warnx("created od-table %s " "(elemsize=%zu, nitems=%zu)", fn, item_size, nitems); exit(0); } pfl_odt_load(&t, &pfl_odtops, oflg, fn, "%s", fn); pfl_odt_check(t, visit, &t); for (i = 0; i < num_puts; i++) { size_t elem; elem = pfl_odt_allocslot(t); pfl_odt_allocitem(t, (void **)&p); snprintf(p, item_size, "... put_number=%d ...", i); pfl_odt_putitem(t, elem, p, 1); PSCFREE(p); } /* XXX find in-use slot to free */ for (i = 0; i < num_free; i++) pfl_odt_freeitem(t, i); pfl_odt_release(t); exit(0); }
/** * pjournal_dump - Dump the contents of a journal file. * @fn: journal filename to query. * @verbose: whether to report stats summary or full dump. * * Each time mds restarts, it writes log entries starting from the very * first slot of the log. Anyway, the function dumps all log entries, * some of them may be from previous incarnations of the MDS. */ void pjournal_dump(const char *fn) { int i, ntotal, nmagic, nchksum, nformat, ndump, first = 1; uint32_t slot, highest_slot = -1, lowest_slot = -1; uint64_t chksum, highest_xid = 0, lowest_xid = 0; struct psc_journal_enthdr *pje; struct psc_journal_hdr *pjh; struct psc_journal *pj; struct stat statbuf; unsigned char *jbuf; ssize_t nb, pjhlen; time_t ts; ntotal = nmagic = nchksum = nformat = ndump = 0; pj = PSCALLOC(sizeof(*pj)); strlcpy(pj->pj_name, pfl_basename(fn), sizeof(pj->pj_name)); pj->pj_fd = open(fn, O_RDWR | O_DIRECT); if (pj->pj_fd == -1) psc_fatal("failed to open journal %s", fn); if (fstat(pj->pj_fd, &statbuf) == -1) psc_fatal("failed to stat journal %s", fn); /* * O_DIRECT may impose alignment restrictions so align the * buffer and perform I/O in multiples of file system block * size. */ pjhlen = PSC_ALIGN(sizeof(*pjh), statbuf.st_blksize); pjh = psc_alloc(pjhlen, PAF_PAGEALIGN); nb = pread(pj->pj_fd, pjh, pjhlen, 0); if (nb != pjhlen) psc_fatal("failed to read journal header"); pj->pj_hdr = pjh; if (pjh->pjh_magic != PJH_MAGIC) psc_fatalx("journal header has a bad magic number " "%#"PRIx64, pjh->pjh_magic); if (pjh->pjh_version != PJH_VERSION) psc_fatalx("journal header has an invalid version " "number %d", pjh->pjh_version); psc_crc64_init(&chksum); psc_crc64_add(&chksum, pjh, offsetof(struct psc_journal_hdr, pjh_chksum)); psc_crc64_fini(&chksum); if (pjh->pjh_chksum != chksum) psc_fatalx("journal header has an invalid checksum " "value %"PSCPRIxCRC64" vs %"PSCPRIxCRC64, pjh->pjh_chksum, chksum); if (S_ISREG(statbuf.st_mode) && statbuf.st_size != (off_t)(pjhlen + pjh->pjh_nents * PJ_PJESZ(pj))) psc_fatalx("size of the journal log %"PSCPRIdOFFT"d does " "not match specs in its header", statbuf.st_size); if (pjh->pjh_nents % pjh->pjh_readsize) psc_fatalx("number of entries %d is not a multiple of the " "readsize %d", pjh->pjh_nents, pjh->pjh_readsize); ts = pjh->pjh_timestamp; printf("%s:\n" " version: %u\n" " entry size: %u\n" " number of entries: %u\n" " batch read size: %u\n" " entry start offset: %"PRId64"\n" " format time: %s" " uuid: %"PRIx64"\n" " %4s %3s %4s %4s %s\n", fn, pjh->pjh_version, PJ_PJESZ(pj), pjh->pjh_nents, pjh->pjh_readsize, pjh->pjh_start_off, ctime(&ts), pjh->pjh_fsuuid, "idx", "typ", "xid", "txg", "details"); jbuf = psc_alloc(PJ_PJESZ(pj) * pj->pj_hdr->pjh_readsize, PAF_PAGEALIGN); for (slot = 0; slot < pjh->pjh_nents; slot += pjh->pjh_readsize) { nb = pread(pj->pj_fd, jbuf, PJ_PJESZ(pj) * pjh->pjh_readsize, PJ_GETENTOFF(pj, slot)); if (nb != PJ_PJESZ(pj) * pjh->pjh_readsize) warn("failed to read %d log entries at slot %d", pjh->pjh_readsize, slot); for (i = 0; i < pjh->pjh_readsize; i++) { ntotal++; pje = (void *)&jbuf[PJ_PJESZ(pj) * i]; if (pje->pje_magic != PJE_MAGIC) { nmagic++; warnx("journal slot %d has a bad magic" "number", slot + i); continue; } /* * If we hit a new entry that is never used, we * assume that the rest of the journal is never * used. */ if (pje->pje_type == PJE_FORMAT) { nformat = nformat + pjh->pjh_nents - (slot + i); goto done; } psc_crc64_init(&chksum); psc_crc64_add(&chksum, pje, offsetof( struct psc_journal_enthdr, pje_chksum)); psc_crc64_add(&chksum, pje->pje_data, pje->pje_len); psc_crc64_fini(&chksum); if (pje->pje_chksum != chksum) { nchksum++; warnx("journal slot %d has a corrupt " "checksum", slot + i); goto done; } ndump++; if (verbose) pjournal_dump_entry(slot + i, pje); if (first) { first = 0; highest_xid = lowest_xid = pje->pje_xid; highest_slot = lowest_slot = slot + i; continue; } if (highest_xid < pje->pje_xid) { highest_xid = pje->pje_xid; highest_slot = slot + i; } if (lowest_xid > pje->pje_xid) { lowest_xid = pje->pje_xid; lowest_slot = slot + i; } } } done: if (close(pj->pj_fd) == -1) printf("failed closing journal %s", fn); psc_free(jbuf, PAF_PAGEALIGN, PJ_PJESZ(pj)); PSCFREE(pj); printf("----------------------------------------------\n" "%8d slot(s) scanned\n" "%8d in use\n" "%8d formatted\n" "%8d bad magic\n" "%8d bad checksum(s)\n" "lowest transaction ID=%#"PRIx64" (slot=%d)\n" "highest transaction ID=%#"PRIx64" (slot=%d)\n", ntotal, ndump, nformat, nmagic, nchksum, lowest_xid, lowest_slot, highest_xid, highest_slot); }