int _mds_fcmh_setattr(int vfsid, struct fidc_membh *f, int to_set, const struct srt_stat *sstb, int log) { struct srt_stat sstb_out; int rc; FCMH_LOCK_ENSURE(f); FCMH_BUSY_ENSURE(f); FCMH_ULOCK(f); if (log) mds_reserve_slot(1); rc = mdsio_setattr(vfsid, fcmh_2_mfid(f), sstb, to_set, &rootcreds, &sstb_out, fcmh_2_mfh(f), log ? mdslog_namespace : NULL); if (log) mds_unreserve_slot(1); if (!rc) { psc_assert(sstb_out.sst_fid == fcmh_2_fid(f)); FCMH_LOCK(f); f->fcmh_sstb = sstb_out; FCMH_ULOCK(f); } return (rc); }
int sli_fcmh_getattr(struct fidc_membh *f) { struct stat stb; if (fstat(fcmh_2_fd(f), &stb) == -1) return (-errno); FCMH_LOCK(f); sl_externalize_stat(&stb, &f->fcmh_sstb); // XXX get ptruncgen and gen f->fcmh_flags |= FCMH_HAVE_ATTRS; FCMH_ULOCK(f); return (0); }
/** * _slm_fcmh_endow - "Endow" or apply inheritance to a new directory * entry from its parent directory replica layout. * Note: the bulk of this is empty until we have a place to store such * info in the SLASH2 metafile. */ int _slm_fcmh_endow(int vfsid, struct fidc_membh *p, struct fidc_membh *c, int wr) { sl_replica_t repls[SL_MAX_REPLICAS]; int nr, rc = 0; uint32_t pol; FCMH_LOCK(p); pol = fcmh_2_ino(p)->ino_replpol; nr = fcmh_2_nrepls(p); memcpy(repls, fcmh_2_ino(p)->ino_repls, sizeof(repls[0]) * SL_DEF_REPLICAS); if (nr > SL_DEF_REPLICAS) { mds_inox_ensure_loaded(fcmh_2_inoh(p)); memcpy(&repls[SL_DEF_REPLICAS], fcmh_2_inox(p)->inox_repls, sizeof(repls[0]) * SL_INOX_NREPLICAS); } FCMH_ULOCK(p); FCMH_WAIT_BUSY(c); fcmh_2_replpol(c) = pol; fcmh_2_ino(c)->ino_nrepls = nr; memcpy(fcmh_2_ino(c)->ino_repls, repls, sizeof(repls[0]) * SL_DEF_REPLICAS); if (nr > SL_DEF_REPLICAS) { mds_inox_ensure_loaded(fcmh_2_inoh(c)); memcpy(fcmh_2_inox(c)->inox_repls, &repls[SL_DEF_REPLICAS], sizeof(repls[0]) * SL_INOX_NREPLICAS); } if (wr) mds_inodes_odsync(vfsid, c, mdslog_ino_repls); FCMH_UNBUSY(c); return (rc); }
int slm_rmc_handle_getattr(struct pscrpc_request *rq) { const struct srm_getattr_req *mq; struct srm_getattr_rep *mp; struct fidc_membh *f; int vfsid; SL_RSX_ALLOCREP(rq, mq, mp); psclog_diag("pfid="SLPRI_FID, mq->fg.fg_fid); if (mq->fg.fg_fid == SLFID_ROOT && use_global_mount) { mp->attr.sst_fg.fg_fid = SLFID_ROOT; mp->attr.sst_fg.fg_gen = FGEN_ANY-1; slm_root_attributes(&mp->attr); return (0); } mp->rc = -slm_fcmh_get(&mq->fg, &f); if (mp->rc) PFL_GOTOERR(out, mp->rc); mp->rc = slfid_to_vfsid(mq->fg.fg_fid, &vfsid); if (mp->rc) PFL_GOTOERR(out, mp->rc); mp->xattrsize = mdsio_hasxattrs(vfsid, &rootcreds, fcmh_2_mfid(f)); FCMH_LOCK(f); mp->attr = f->fcmh_sstb; out: if (f) fcmh_op_done(f); return (0); }
int msl_fcmh_fetch_inode(struct fidc_membh *f) { struct slrpc_cservice *csvc = NULL; struct pscrpc_request *rq = NULL; struct srm_get_inode_req *mq; struct srm_get_inode_rep *mp; struct fcmh_cli_info *fci; int rc; fci = fcmh_2_fci(f); rc = slc_rmc_getcsvc(fci->fci_resm, &csvc); if (rc) goto out; rc = SL_RSX_NEWREQ(csvc, SRMT_GET_INODE, rq, mq, mp); if (rc) goto out; mq->fg = f->fcmh_fg; rc = SL_RSX_WAITREP(csvc, rq, mp); if (rc == 0) rc = mp->rc; if (rc) goto out; FCMH_LOCK(f); msl_fcmh_stash_inode(f, &mp->ino); FCMH_ULOCK(f); out: if (rq) pscrpc_req_finished(rq); if (csvc) sl_csvc_decref(csvc); return (rc); }
/* * Update the high-level app stat(2)-like attribute buffer for a FID * cache member. * @f: FID cache member to update. * @sstb: incoming stat attributes. * @flags: behavioral flags. * Notes: * (1) if SAVELOCAL has been specified, save local field values: * (o) file size * (o) mtime * (2) This function should only be used by a client. */ void slc_fcmh_setattrf(struct fidc_membh *f, struct srt_stat *sstb, int flags) { uidmap_int_stat(sstb); if (flags & FCMH_SETATTRF_HAVELOCK) FCMH_LOCK_ENSURE(f); else FCMH_LOCK(f); if (fcmh_2_gen(f) == FGEN_ANY) fcmh_2_gen(f) = sstb->sst_gen; if ((FID_GET_INUM(fcmh_2_fid(f))) != SLFID_ROOT && fcmh_2_gen(f) > sstb->sst_gen) { OPSTAT_INCR("msl.generation-backwards"); DEBUG_FCMH(PLL_DIAG, f, "attempt to set attr with " "gen %"PRIu64" from old gen %"PRIu64, fcmh_2_gen(f), sstb->sst_gen); goto out; } /* * If we don't have stat attributes, how can we save our local * updates? */ if ((f->fcmh_flags & FCMH_HAVE_ATTRS) == 0) flags |= FCMH_SETATTRF_CLOBBER; /* * Always update for roots because we might have faked them * with readdir at the super root. */ if ((FID_GET_INUM(fcmh_2_fid(f))) == SLFID_ROOT) flags |= FCMH_SETATTRF_CLOBBER; psc_assert(sstb->sst_gen != FGEN_ANY); psc_assert(f->fcmh_fg.fg_fid == sstb->sst_fid); /* * The default behavior is to save st_size and st_mtim since we * might have done I/O that the MDS does not know about. */ if ((flags & FCMH_SETATTRF_CLOBBER) == 0 && fcmh_isreg(f)) { /* * If generation numbers match, take the highest of the * values. Otherwise, disregard local values and * blindly accept whatever the MDS tells us. */ if (fcmh_2_ptruncgen(f) == sstb->sst_ptruncgen && fcmh_2_gen(f) == sstb->sst_gen && fcmh_2_fsz(f) > sstb->sst_size) sstb->sst_size = fcmh_2_fsz(f); if (fcmh_2_utimgen(f) == sstb->sst_utimgen) sstb->sst_mtim = f->fcmh_sstb.sst_mtim; } COPY_SSTB(sstb, &f->fcmh_sstb); f->fcmh_flags |= FCMH_HAVE_ATTRS; f->fcmh_flags &= ~FCMH_GETTING_ATTRS; if (sl_fcmh_ops.sfop_postsetattr) sl_fcmh_ops.sfop_postsetattr(f); DEBUG_FCMH(PLL_DEBUG, f, "attr set"); out: if (!(flags & FCMH_SETATTRF_HAVELOCK)) FCMH_ULOCK(f); }
int mds_repl_delrq(const struct sl_fidgen *fgp, sl_bmapno_t bmapno, sl_bmapno_t *nbmaps, sl_replica_t *iosv, int nios) { int tract[NBREPLST], rc, iosidx[SL_MAX_REPLICAS], flags; sl_bmapno_t nbmaps_processed = 0; struct slm_repl_valid replv; struct fidc_membh *f = NULL; struct bmap *b; if (nios < 1 || nios > SL_MAX_REPLICAS || *nbmaps == 0) return (-EINVAL); rc = slm_fcmh_get(fgp, &f); if (rc) return (-rc); FCMH_LOCK(f); if (fcmh_isdir(f)) flags = IOSV_LOOKUPF_DEL; else flags = IOSV_LOOKUPF_LOOKUP; /* Find replica IOS indexes. */ rc = -_mds_repl_iosv_lookup(current_vfsid, fcmh_2_inoh(f), iosv, iosidx, nios, flags); if (fcmh_isdir(f) || rc) PFL_GOTOERR(out, rc); replv.nios = nios; replv.idx = iosidx; brepls_init(tract, -1); tract[BREPLST_REPL_QUEUED] = BREPLST_GARBAGE_QUEUED; tract[BREPLST_REPL_SCHED] = BREPLST_GARBAGE_QUEUED; tract[BREPLST_VALID] = BREPLST_GARBAGE_QUEUED; /* Wildcards shouldn't result in errors on zero-length files. */ if (*nbmaps != (sl_bmapno_t)-1) rc = -SLERR_BMAP_INVALID; /* * The following loop will bail out on the very first error. * However, its previous action, if any, has already taken * effect. */ for (; *nbmaps && bmapno < fcmh_nvalidbmaps(f); bmapno++, --*nbmaps, nbmaps_processed++) { if (nbmaps_processed >= SLM_REPLRQ_NBMAPS_MAX) PFL_GOTOERR(out, rc = -PFLERR_WOULDBLOCK); rc = -bmap_get(f, bmapno, SL_WRITE, &b); if (rc) PFL_GOTOERR(out, rc); /* * Before blindly doing the transition, we have to check * to ensure this operation would retain at least one * valid replica. */ replv.n = 0; mds_repl_bmap_walkcb(b, NULL, NULL, 0, slm_repl_countvalid_cb, &replv); flags = 0; if (replv.n == 0) rc = -SLERR_LASTREPL; else { rc = _mds_repl_bmap_walk(b, tract, NULL, 0, iosidx, nios, slm_repl_delrq_cb, &flags); psc_assert(!rc); if (flags & FLAG_DIRTY) rc = mds_bmap_write_logrepls(b); } bmap_op_done_type(b, BMAP_OPCNT_LOOKUP); if (rc) PFL_GOTOERR(out, rc); } out: if (f) fcmh_op_done(f); *nbmaps = nbmaps_processed; return (rc); }