// XXX could ideally try to find the newest version over // all replicas and move that everywhere. // This ought to do that eventually... void dhblock_keyhash_srv::real_repair (blockID key, ptr<location> me, u_int32_t *myaux, ptr<location> them, u_int32_t *theiraux) { // keyhash aux is the version number of the block. ptr<location> s = NULL; // We calculate our own source? ptr<repair_job> job; if (!myaux) { // We're missing, so fetch it. job = New refcounted<rjrep> (key, s, me, mkref (this)); repair_add (job); } else { // They're missing so push it. // Otherwise, move towards the newer one. if (!theiraux) { job = New refcounted<rjrep> (key, s, them, mkref (this)); repair_add (job); } else if (*theiraux < *myaux) { job = New refcounted<rjrep> (key, s, them, mkref (this)); repair_add (job); } else if (*theiraux > *myaux) { job = New refcounted<rjrep> (key, s, me, mkref (this)); repair_add (job); } } }
void unixfd::rcb () { if (reof) { fdcb (localfd_in, selread, NULL); return; } char buf[16*1024]; int fdrecved = -1; ssize_t n; if (unixsock) n = readfd (localfd_in, buf, sizeof (buf), &fdrecved); else n = read (localfd_in, buf, sizeof (buf)); if (n < 0) { if (errno != EAGAIN) abort (); return; } if (!n) { readeof (); return; } else { rex_payload arg; arg.channel = channo; arg.fd = fd; arg.data.set (buf, n); if (fdrecved >= 0) { close_on_exec (fdrecved); rex_newfd_arg arg; arg.channel = channo; arg.fd = fd; ref<rex_newfd_res> resp (New refcounted<rex_newfd_res> (false)); proxy->call (REX_NEWFD, &arg, resp, wrap (mkref (this), &unixfd::newfdcb, fdrecved, resp)); } ref<bool> pres (New refcounted<bool> (false)); rsize += n; proxy->call (REX_DATA, &arg, pres, wrap (mkref (this), &unixfd::datacb, n, pres)); } if (rsize >= hiwat) fdcb (localfd_in, selread, NULL); }
afsdirentry::afsdirentry (afsdir *dir, const str &name, afsnode *node) : dir (dir), name (name), node (mkref (node)), cookie (gencookie ()) { node->addlink (); cookietab.insert (this); dir->entries.insert (this); }
void aios::input () { if (rlock) return; rlock = true; ref<aios> hold = mkref (this); // Don't let this be freed under us int n = ::readv (fd, const_cast<iovec *> (inb.iniov ()), inb.iniovcnt ()); if (n > 0) inb.addbytes (n); else if (n < 0 && errno != EAGAIN) { fail (errno); rlock = false; return; } else if (!n && !(this->*infn) ()) { fail (0); rlock = false; return; } while ((this->*infn) ()) ; if (fd >= 0) { if (rcb) fdcb (fd, selread, wrap (this, &aios::input)); else fdcb (fd, selread, NULL); //timeoutbump (); } rlock = false; }
ref<sfsserver_auth::userauth> sfsserver_auth::userauth_alloc (sfs_aid aid) { ref<userauth> uap (New refcounted<userauth> (aid, mkref (this))); uap->sendreq (); return uap; }
void afsusrroot::nfs_lookup (svccb *sbp, str name) { afsnode *e = lookup (name, aid); if (e) { if (int err = srvinfo::geterr (name)) nfs_error (sbp, err); else lookup_reply (sbp, e); return; } else if ((!sfs_parsepath (name) && (!namedprotrx.match (name) /*|| !nptab[namedprotrx[1]]*/)) || terminating) { nfs_error (sbp, ENOENT); return; } ref<delaypt> dpt = delaypt::alloc (); ref<setupstate> ss = New refcounted<setupstate> (name, dpt); link (dpt, name); if (ptr<aclnt> ch = agentc ()) ch->timedcall (agent_timeout, AGENTCB_REVOKED, &name, &ss->revres, wrap (mkref (this), &afsusrroot::revcb, ss)); else { ss->revdone = true; finish (ss, NFS_OK); } lookup_reply (sbp, afsdir::lookup (name, aid)); }
void aios::output () { ref<aios> hold = mkref (this); // Don't let this be freed under us suio *out = outb.tosuio (); int res; if (fdsendq.empty ()) res = out->output (fd); else { int cnt = out->iovcnt (); if (cnt > UIO_MAXIOV) cnt = UIO_MAXIOV; res = writevfd (fd, out->iov (), cnt, fdsendq.front ()); if (res > 0) { out->rembytes (res); ::close (fdsendq.pop_front ()); } else if (res < 0 && errno == EAGAIN) res = 0; } if (res < 0) { fail (errno); return; } if (res > 0) timeoutbump (); if (weof && !out->resid ()) shutdown (fd, SHUT_WR); wblock = !res; setoutcb (); }
rexfd::rexfd (rexchannel *pch, int fd) : pch (pch), proxy (pch->get_proxy ()), channo (pch->get_channo ()), fd (fd) { /* warn << "--reached rexfd\n"; */ if (fd < 0) fatal ("attempt to create negative fd: %d\n", fd); pch->insert_fd (fd, mkref (this)); }
void vnode_impl::get_predecessor (ptr<location> n, cbchordID_t cb) { ptr<chordID> v = New refcounted<chordID> (n->id ()); ngetpredecessor++; chord_noderes *res = New chord_noderes (CHORD_OK); doRPC (n, chord_program_1, CHORDPROC_GETPREDECESSOR, v, res, wrap (mkref (this), &vnode_impl::get_predecessor_cb, n->id (), cb, res)); }
void vnode_impl::get_succlist (ptr<location> n, cbchordIDlist_t cb) { ngetsucclist++; chord_nodelistres *res = New chord_nodelistres (CHORD_OK); ptr<chordID> v = New refcounted<chordID> (n->id ()); doRPC (n, chord_program_1, CHORDPROC_GETSUCCLIST, v, res, wrap (mkref (this), &vnode_impl::get_succlist_cb, cb, res)); }
void vnode_impl::get_successor (ptr<location> n, cbchordID_t cb) { // warn << "get successor of " << n << "\n"; ngetsuccessor++; chord_noderes *res = New chord_noderes (CHORD_OK); ptr<chordID> v = New refcounted<chordID> (n->id ()); doRPC (n, chord_program_1, CHORDPROC_GETSUCCESSOR, v, res, wrap (mkref (this), &vnode_impl::get_successor_cb, n->id (), cb, res)); }
void afsusrroot::finish (ref<setupstate> ss, int err) { if (!ss->dpt) return; if (!err) err = srvinfo::geterr (ss->name); if (err) { ss->dpt->setres (nfsstat (err)); ss->dpt = NULL; delaycb (15, wrap (afsdir_unlink, mkref (this), ss->name)); return; } if (!ss->revdone) return; afsnode *e = lookup (ss->name, NULL); if (!e || e == ss->dpt) e = afs_sfsroot->lookup (ss->name, NULL); if (e) { str name = ss->name; unlink (name); link (e, name); #if FIX_MNTPOINT if (opt_fix_mntpoint) { if (str res = e->readlink ()) ss->dpt->setres (res); else { warn << "afsusrroot::finish: shouldn't get here (please report bug)\n"; ss->dpt->setres (strbuf ("%s/%s", sfsroot, ss->name.cstr ())); ss->dpt->setres (strbuf ("%s/" MPDOT "%s/r", sfsroot, ss->name.cstr ())); } } else #endif /* FIX_MNTPOINT */ ss->dpt->setres (strbuf ("%s/%s", sfsroot, ss->name.cstr ())); } else srvinfo::alloc (ss->name, wrap (mkref (this), &afsusrroot::finish, ss)); }
void ping_start() { if (self_.mid == view_.primary.mid) { ping_incoming_.clear(); ping_timeout_cb_ = delaycb(periodic_primary_ping + timeout_primary_ping, wrap(mkref(this), &cohort::ping_check_incoming)); } else { ping_timeout_cb_ = delaycb(periodic_primary_ping, wrap(mkref(this), &cohort::ping_start)); } ping_arg arg; arg.myid = self_.mid; arg.vid = view_.vid; sockaddr_in sin = netaddr2sockaddr(view_.primary.addr); ref<ping_res> resp = New refcounted<ping_res>(); c_->timedcall(timeout_primary_ping, REP_PING, &arg, resp, wrap(mkref(this), &cohort::ping_cb, view_.vid, resp), 0, 0, 0, 0, 0, (sockaddr *) &sin); }
void vnode_impl::alert (ptr<location> n, ptr<location> x) { ptr<chord_nodearg> na = New refcounted<chord_nodearg>; chordstat *res = New chordstat; nalert++; warnx << "alert: " << x->id() << " died; notify " << n->id () << "\n"; x->fill_node (na->n); doRPC (n, chord_program_1, CHORDPROC_ALERT, na, res, wrap (mkref (this), &vnode_impl::alert_cb, res)); }
void vnode_impl::notify (ptr<location> n, chordID &x) { ptr<chord_nodearg> na = New refcounted<chord_nodearg>; chordstat *res = New chordstat; nnotify++; // warnx << gettime () << ": notify " << n << " about " << x << "\n"; locations->lookup (x)->fill_node (na->n); doRPC (n, chord_program_1, CHORDPROC_NOTIFY, na, res, wrap (mkref (this), &vnode_impl::notify_cb, n->id (), res)); }
int aios::flush () { ptr<aios> hold; if (fd >= 0 && outb.tosuio ()->resid ()) { hold = mkref (this); // Don't let this be freed under us make_sync (fd); output (); _make_async (fd); } return err; }
void asrv::seteof (ref<xhinfo> xi, const sockaddr *src, bool force) { if (force || xi->xh->connected) { asrv *s; ptr<asrv> sp; for (s = xi->stab.first (); s; s = xi->stab.next (s)) { sp = mkref (s); if (s->cb) (*s->cb) (NULL); } } }
void chord::tcpclient_cb (int srvfd) { int fd = accept (srvfd, NULL, NULL); if (fd < 0) warn << "chord: accept failed " << strerror (errno) << "\n"; else { ptr<axprt> x = axprt_stream::alloc (fd, 230000); ptr<asrv> s = asrv::alloc (x, transport_program_1); s->setcb (wrap (mkref(this), &chord::dispatch, s)); } }
void svccb::init (asrv *s, const sockaddr *src) { srv = mkref (s); srv->xi->svcadd (); if (!s->xi->xh->connected) { addrlen = s->xi->xh->socksize; addr = (sockaddr *) opnew (addrlen); memcpy (addr, src, addrlen); } // keep track of when this RPC started ts_start = sfs_get_tsnow(); }
void start () { char tfile[80]; sprintf (tfile, "aio.%02d~", fctr++); path = tfile; str msg ("This is " << path << ".\n"); buf = a->bufalloc (msg.len () + 1); if (!buf) { a->bufwait (wrap (this, &aiotst::start)); return; } strcpy (buf->base (), msg); a->open (path, O_CREAT|O_RDWR|O_TRUNC, 0666, wrap (mkref (this), &aiotst::opencb)); a->finalize (); }
void client::rmdircb_1 (svccb *sbp, void *_res, lookup3res *lres, filesrv::reqstate rqs, ptr<acltargetlist> targets, clnt_stat err) { AUTH *auth = auth_sfs; if (err || !lres || lres->status || !auth) { warn << "RMDIR: failed because LOOKUP failed\n"; reject_nfs (sbp, targets, NFS3ERR_SERVERFAULT); if (lres) delete lres; return; } ptr<nfs_fh3> fhp = New refcounted<nfs_fh3>; if (!get_lookupresfh (lres, fhp)) { warn << "RMDIR: Failed to get fh for the dir we're deleting."; delete lres; reject_nfs (sbp, targets, NFS3ERR_SERVERFAULT); return; } if (lres->resok->obj_attributes.present && lres->resok->obj_attributes.attributes->type != NF3DIR) { warn << "RMDIR: Lookup did not return a fh for a directory\n"; delete lres; reject_nfs (sbp, targets, NFS3ERR_SERVERFAULT); return; } // this is a workaround wrap()'s 7 argument limitation ref<sbpandres> sr = New refcounted<sbpandres>; sr->sbp = sbp; sr->res = _res; readdir3args readdirargs; readdirargs.dir = *fhp; readdirargs.cookie = 0; readdirargs.count = 8192; readdir3res *rres = New readdir3res; rqs.c->call (NFSPROC3_READDIR, &readdirargs, rres, wrap (mkref (this), &client::rmdircb_2, sr, rres, fhp, rqs, targets), auth); delete lres; }
void client::aclresolve_type (svccb *sbp, filesrv::reqstate rqs, ptr<acltargetlist> targets) { acltarget *entry = targets->next_entry (); assert (entry); assert (entry->get_objecttype () == unknown); nfs_fh3 *args = entry->get_objectfhp (); getattr3res *res = New getattr3res; rqs.c->call (NFSPROC3_GETATTR, args ,res, wrap (mkref (this), &client::aclresolve_type_cb, sbp, rqs, res, targets), auth_sfs); }
void chord::startchord () { assert (fd_stream > 0 || fd_dgram > 0); if (fd_dgram > 0) { x_dgram = axprt_dgram::alloc (fd_dgram, sizeof(sockaddr), 230000); ptr<asrv> s = asrv::alloc (x_dgram, transport_program_1); s->setcb (wrap (mkref(this), &chord::dispatch, s)); } if (fd_stream > 0) { int ret = listen (fd_stream, 1000); if (ret < 0) fatal ("listen (%d, 1000): %m\n", fd_stream); fdcb (fd_stream, selread, wrap (this, &chord::tcpclient_cb, fd_stream)); } }
void client::rmdircb_2 (ptr<sbpandres> sr, readdir3res *rres, ptr<nfs_fh3> fhp, filesrv::reqstate rqs, ptr<acltargetlist> targets, clnt_stat err) { AUTH *auth = auth_sfs; if (err || !rres || rres->status || !auth) { warn << "RMDIR: failed because READDIR failed\n"; reject_nfs (sr->sbp, targets, NFS3ERR_SERVERFAULT); if (rres) delete rres; return; } int n = 0; entry3 *ep = rres->resok->reply.entries; if (ep) for (;;) { n++; entry3 *nep = ep->nextentry; if (!nep) break; ep = nep; } // assume that 3 means ".", "..", and ".SFSACL" if (n > 3) { warn << "RMDIR: directory isn't empty\n"; reject_nfs (sr->sbp, targets, NFS3ERR_NOTEMPTY); delete rres; return; } diropargs3 removeargs; removeargs.dir = *fhp; removeargs.name = SFSDIRACL; wccstat3 *wres = New wccstat3; rqs.c->call (NFSPROC3_REMOVE, &removeargs, wres, wrap (mkref (this), &client::rmdircb_3, sr->sbp, sr->res, wres, rqs, targets), auth); delete rres; }
void axprt_dgram::input () { ref<axprt> hold (mkref (this)); // Don't let this be freed under us for (size_t tot = 0; cb && tot < pktsize;) { socklen_t ss = socksize; bzero (sabuf, ss); ssize_t ps = recvfrom (fd, pktbuf, pktsize, 0, sabuf, &ss); if (ps < 0) { if (errno != EAGAIN && connected) (*cb) (NULL, -1, NULL); return; } tot += ps; (*cb) (pktbuf, ps, sabuf); } }
afsnode * afsusrdir::lookup (const str &name, sfs_aid rqaid) { if (afsnode *n = afsdir::lookup (name, aid)) return n; ptr<aclnt> ch; if (negcache[name] || !nameok (name) || !(ch = agentc ())) return NULL; ref<delaypt> dpt = delaypt::alloc (); link (dpt, name); sfs_filename lname = path ? str (path << "/" << name) : name; ref<sfsagent_lookup_res> resp = New refcounted<sfsagent_lookup_res>; ch->timedcall (agent_timeout, AGENTCB_LOOKUP, &lname, resp, wrap (mkref (this), &afsusrdir::lookup_cb, name, dpt, resp)); return dpt; }
//after mkdir, we must write the new dir's acl //first, create the new file and in create_diracl_cb //if creation worked, use write_acl (as in the case of newly-created file) //to write the acl void client::create_diracl (svccb *sbp, void *res, filesrv::reqstate rqs, ptr<acltargetlist> targets, nfs_fh3 fh) { create3args cargs; diropres3 *cres = New diropres3; cargs.where.dir = fh; cargs.where.name = SFSDIRACL; cargs.how.set_mode (UNCHECKED); cargs.how.obj_attributes->mode.set_set (true); *cargs.how.obj_attributes->mode.val = CREATEACL_MODE; rqs.c->call (NFSPROC3_CREATE, &cargs, cres, wrap (mkref (this), &client::create_diracl_cb, sbp, res, rqs, targets, cres), auth_sfs); }
//we have a dir, so get fh for /.SFSACL void client::aclresolve_dir (svccb *sbp, filesrv::reqstate rqs, ptr<acltargetlist> targets) { acltarget *entry = targets->next_entry (); assert (entry); assert (entry->get_objecttype () == dir); diropargs3 args; args.dir = *entry->get_objectfhp (); args.name = SFSDIRACL; lookup3res *res = New lookup3res; rqs.c->call (NFSPROC3_LOOKUP, &args ,res, wrap (mkref (this), &client::aclresolve_dir_cb, sbp, rqs, res, targets), auth_sfs); }
//go read the acl void client::aclresolve_file (svccb *sbp, filesrv::reqstate rqs, ptr<acltargetlist> targets) { acltarget *entry = targets->next_entry (); assert (entry); assert (entry->aclfh_known ()); read3args args; args.file = *entry->get_aclfhp (); args.offset = ACLOFFSET; args.count = ACLSIZE; read3res *res = New read3res; rqs.c->call (NFSPROC3_READ, &args, res, wrap (mkref (this), &client::aclresolve_file_cb, sbp,rqs, res, targets), auth_sfs); }
void sfsserver_auth::userauth::aresult (clnt_stat err) { cbase = NULL; if (err) { warn << "sfscd: " << err << "\n"; finish (); } else if (!ares.authenticate) finish (); else { sfs_loginarg arg; arg.seqno = seqno; arg.certificate = *ares.certificate; sp->sfsc->call (SFSPROC_LOGIN, &arg, &sres, wrap (mkref (this), &sfsserver_auth::userauth::sresult), NULL, NULL, xdr_sfs_loginres_old); } }