⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 chord 源码 http://pdos.csail.mit.edu/chord/
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * Copyright (C) 2001  Josh Cates (cates@mit.edu), *                     Frank Dabek (fdabek@lcs.mit.edu),  *   		       Massachusetts Institute of Technology *  * *  Permission is hereby granted, free of charge, to any person obtaining *  a copy of this software and associated documentation files (the *  "Software"), to deal in the Software without restriction, including *  without limitation the rights to use, copy, modify, merge, publish, *  distribute, sublicense, and/or sell copies of the Software, and to *  permit persons to whom the Software is furnished to do so, subject to *  the following conditions: * *  The above copyright notice and this permission notice shall be *  included in all copies or substantial portions of the Software. * *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */// KNOWN ISSUES://   * READDIR//     - client always re-requests entries in a directory, why?//   * READDIRP//     - completely broken/not really implemented//   * READ//     - does not deal with request which span blocks//     - pre-fetching not implemented//   * LOOKUP//     - linear scan algo could be improved, to return NOENT//       when it is sure that the entry does not exists//     - or binary lookup could be implemented//   * GENERAL//     - possibly, embedded inodes to improve LOOKUP performance//     - can make lots of optimizations to filesystem structure which are easy when//       the FS is read-only, but hard in a read-write filesystem, namely embedded inodes//     - copy the dispatch routine from sfsrocd//   * XXX//     - search for this and find more things to fix// // fileids == lower_64_bits (sha1(path))// sfs_hash == chordID == nfs_fh3//#include <dhash_common.h>#include <dhblock_keyhash.h>#include "chordcd.h"#include "rxx.h"#include "arpc.h"#include "xdr_suio.h"#include "afsnode.h"#include "id_utils.h"#define LSD_SOCKET "/tmp/chord-sock"#define CMTU 1024#define PREFETCH_BLOCKS 8static void splitpath (vec<str> &out, str in);static fattr3 ro2nfsattr (sfsro_inode *si);// XXX keep in sync with same function in sfsrodb/sfsrodb.Cstatic uint64path2fileid(const str path){  char buf[sha1::hashsize];  bzero(buf, sha1::hashsize);  sha1_hash (buf, path.cstr (), path.len ());  return gethyper (buf); // XXX not using all 160 bits of the hash}chord_server::chord_server (u_int cache_maxsize)  : dh (LSD_SOCKET), data_cache (cache_maxsize){}voidchord_server::setrootfh (str root, cbfh_t rfh_cb){  static rxx path_regexp ("chord:([0-9a-zA-Z+-]*)$");  if (!path_regexp.search (root)) {    warn << "Malformated root filesystem name: " << root << "\n";    (*rfh_cb) (NULL);  }  else {    str rootfhstr = path_regexp[1];    chordID ID;    if (!str2chordID (rootfhstr, ID)) {      warn << "Malformed root filesystem name: " << root << "\n";      (*rfh_cb) (NULL);    }    warn << "reading root " << ID << "\n";    //fetch the root file handle too..    fetch_data (false, ID, DHASH_KEYHASH, 		wrap (this, &chord_server::getroot_fh, rfh_cb));  }}voidchord_server::getroot_fh (cbfh_t rfh_cb, ptr<sfsro_data> d){  if (!d) {    warn << "root block was null\n";    (*rfh_cb) (NULL);  } else if (d->type  != CFS_FSINFO) {    warn << "root block had wrong type\n";    (*rfh_cb) (NULL);  } else {    warn << "Mounted filesystem.\n";    warn << "  start     : " << ctime((time_t *)&(d->fsinfo->start));    warn << "  duration  : " << d->fsinfo->duration  << " seconds \n";    warn << "  blocksize : " << d->fsinfo->blocksize << "\n";    this->rootdirID = d->fsinfo->rootfh;    this->fsinfo = *d->fsinfo;    fetch_data (false, rootdirID, wrap (this, &chord_server::getrootdir_cb, rfh_cb));  }} voidchord_server::getrootdir_cb (cbfh_t rfh_cb, ptr<sfsro_data> data){  if (data && data->type == SFSRO_INODE && data->inode->type == SFSRODIR) {    this->rootdir = data;    // XXX verify file handle    nfs_fh3 *fh = New nfs_fh3;    chordid_to_nfsfh (&rootdirID, fh);    (*rfh_cb) (fh);  } else {    warn << "root directory invalid\n";    (*rfh_cb) (NULL);  }}voidchord_server::dispatch (ref<nfsserv> ns, nfscall *sbp){  switch(sbp->proc()) {  case NFSPROC3_READLINK:    {    nfs_fh3 *nfh = sbp->Xtmpl getarg<nfs_fh3> ();    chordID fh = nfsfh_to_chordid (nfh);    fetch_data (false, fh, wrap (this, &chord_server::readlink_inode_cb, sbp, fh));    }    break;  case NFSPROC3_GETATTR:     {      nfs_fh3 *nfh = sbp->Xtmpl getarg<nfs_fh3> ();      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::getattr_inode_cb, sbp, fh));    }    break;  case NFSPROC3_FSSTAT:    {      fsstat3res res (NFS3_OK);      rpc_clear (res);      sbp->reply (&res);    }    break;  case NFSPROC3_FSINFO:    {      int blocksize = fsinfo.blocksize;      fsinfo3res res (NFS3_OK);      res.resok->rtmax = blocksize;      res.resok->rtpref = blocksize;      res.resok->rtmult = 512;      res.resok->wtmax = blocksize;      res.resok->wtpref = blocksize;      res.resok->wtmult = 8192;      res.resok->dtpref = blocksize;      res.resok->maxfilesize = INT64 (0x7fffffffffffffff);      res.resok->time_delta.seconds = 0;      res.resok->time_delta.nseconds = 1;      res.resok->properties = (FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS);      sbp->reply (&res);    }    break;  case NFSPROC3_ACCESS:    {      access3args *aa = sbp->Xtmpl getarg<access3args> ();      nfs_fh3 *nfh = &(aa->object);      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::access_inode_cb, sbp, fh));    }    break;  case NFSPROC3_LOOKUP:     {      diropargs3 *dirop = sbp->Xtmpl getarg<diropargs3> ();      nfs_fh3 *nfh = &(dirop->dir);      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::lookup_inode_cb, sbp, fh));    }    break;  case NFSPROC3_READDIR:    {      readdir3args *readdirop = sbp->Xtmpl getarg<readdir3args> ();      nfs_fh3 *nfh = &(readdirop->dir);      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::readdir_inode_cb, sbp, fh));    }    break;  case NFSPROC3_READDIRPLUS:    {      readdirplus3args *readdirop = sbp->Xtmpl getarg<readdirplus3args> ();      nfs_fh3 *nfh = &(readdirop->dir);      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::readdirp_inode_cb, sbp, fh));    }    break;  case NFSPROC3_READ:    {      read3args *ra = sbp->Xtmpl getarg<read3args> ();      nfs_fh3 *nfh = &(ra->file);      chordID fh = nfsfh_to_chordid (nfh);      fetch_data (false, fh, wrap (this, &chord_server::read_inode_cb, sbp, fh));    }    break;  case NFSPROC3_NULL:    {      sbp->reply (NULL);      return;    }    break;  case NFSPROC_CLOSE:    break;  default:    {      sbp->error (NFS3ERR_ROFS);      return;    }    break;  }}// ---------------- operations ---------------voidchord_server::readlink_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data){  if (!data)    sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);      else if (data->inode->type != SFSROLNK)    sbp->error (NFS3ERR_IO);  else if (data->inode->lnk->dest.len () <= 0)    sbp->error (NFS3ERR_INVAL);  else {    readlink3res nfsres (NFS3_OK);    nfsres.resok->data = data->inode->lnk->dest;    sbp->reply(&nfsres);  }}voidchord_server::getattr_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data) {  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);      else {    getattr3res nfsres (NFS3_OK);    *nfsres.attributes = ro2nfsattr (data->inode);    sbp->reply (&nfsres);  }}voidchord_server::access_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data) {  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);      else {    access3args *aa = sbp->Xtmpl getarg<access3args> ();    uint32 access_req = aa->access;    access3res nfsres (NFS3_OK);        nfsres.resok->access = access_check (data->inode, access_req);        sbp->reply (&nfsres);  }}uint32chord_server::access_check(sfsro_inode *ip, uint32 access_req){  uint32 r = 0;  switch (ip->type) {   case SFSRODIR:    r = ACCESS3_READ | ACCESS3_LOOKUP;    break;  case SFSRODIR_OPAQ:    r = ACCESS3_LOOKUP;    break;  case SFSROREG_EXEC:    r = ACCESS3_READ | ACCESS3_EXECUTE;    break;  case SFSROLNK:  case SFSROREG:    r = ACCESS3_READ;    break;  }  return (access_req & r);}voidchord_server::lookup_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data){  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);  else if (data->inode->type != SFSRODIR && data->inode->type != SFSRODIR_OPAQ)    sbp->error (NFS3ERR_NOTDIR);  else {    diropargs3 *dirop = sbp->Xtmpl getarg<diropargs3> ();    lookup (data, ID, dirop->name,	    wrap (this, &chord_server::lookup_lookup_cb, sbp, data, ID));  }}voidchord_server::lookup_lookup_cb (nfscall *sbp, ptr<sfsro_data> dirdata, chordID dirID, 				ptr<sfsro_data> data, chordID dataID, nfsstat3 status){  if (status == NFS3_OK) {    lookup3res *nfsres = sbp->Xtmpl getres<lookup3res> ();    nfsres->set_status (NFS3_OK);    nfsres->resok->dir_attributes.set_present (true);    *nfsres->resok->dir_attributes.attributes = ro2nfsattr (dirdata->inode);    nfs_fh3 nfh;    chordid_to_nfsfh (&dataID, &nfh);        nfsres->resok->object = nfh;    nfsres->resok->obj_attributes.set_present (true);    *nfsres->resok->obj_attributes.attributes =  ro2nfsattr (data->inode);    sbp->reply (nfsres);  } else {    sbp->error (status);  }}voidchord_server::readdir_inode_cb (nfscall *sbp, chordID dataID, ptr<sfsro_data> data){  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);  else if (data->inode->type != SFSRODIR && data->inode->type != SFSRODIR_OPAQ)    sbp->error (NFS3ERR_NOTDIR);  else {    readdir3args *nfsargs = sbp->Xtmpl getarg<readdir3args> ();    uint32 blockno = nfsargs->cookie >> 32;    read_file_data (false, blockno, data->inode->reg, 		    wrap (this, &chord_server::readdir_fetch_dirdata_cb,			  sbp, data, dataID));  }}voidchord_server::readdir_fetch_dirdata_cb (nfscall *sbp,					ptr<sfsro_data> dirInodeData,					chordID dirInodeID,					ptr<sfsro_data> dirblk){  if (dirblk == NULL) {      sbp->error (NFS3ERR_IO);  } else if (dirblk->type != SFSRO_DIRBLK) {      sbp->error (NFS3ERR_IO);  } else {    readdir3args *nfsargs = sbp->Xtmpl getarg<readdir3args> ();    uint32 blockno = nfsargs->cookie >> 32;    uint32 entryno = (uint32)nfsargs->cookie;    sfsro_directory *dir = dirblk->dir;    readdir3res nfsres (NFS3_OK);    nfsres.resok->dir_attributes.set_present (true);    *nfsres.resok->dir_attributes.attributes = ro2nfsattr(dirInodeData->inode);    nfsres.resok->reply.eof = false;    rpc_ptr<entry3> *direntp = &nfsres.resok->reply.entries;    sfsro_dirent *roe = dir->entries;    int space = nfsargs->count - 184; // reserve hdr and trailing NULL dirent    //warn << "------ cookie " << nfsargs->cookie << " ---------\n";    for (uint i = 1; space > 0 && roe ; roe = roe->nextentry, i++) {      if (i <= entryno)	continue;      //warn << "i " << i << ", entryno " << entryno  << ", space " << space;      //warn << ", roe[" << roe->name << ", fileid " << roe->fileid << "]\n";      space -= ((roe->name.len() + 3) & ~3) + 24; // marshaled entry size      if (space >= 0) {	(*direntp).alloc ();	(*direntp)->name = roe->name;	(*direntp)->fileid = roe->fileid;	(*direntp)->cookie = (uint64 (blockno)) << 32 | i;	if (!roe)	  (*direntp)->cookie = (uint64 (blockno + 1)) << 32;	direntp = &(*direntp)->nextentry;      }    }        nfsres.resok->reply.eof = (!roe && dir->eof);    sbp->reply (&nfsres);  }}voidchord_server::readdirp_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data){  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);  else if (data->inode->type != SFSRODIR && data->inode->type != SFSRODIR_OPAQ)    sbp->error (NFS3ERR_NOTDIR);  else {    fetch_data (false, sfshash_to_chordid(&data->inode->reg->direct[0]),		wrap (this, &chord_server::readdirp_fetch_dir_data, 		      sbp, data, ID));  }}voidchord_server::readdirp_fetch_dir_data (nfscall *sbp, ptr<sfsro_data> dirdata,				       chordID dirID,				       ptr<sfsro_data> data) {  sfsro_directory *dir = data->dir;  readdirplus3args *readdirop = sbp->Xtmpl getarg<readdirplus3args> ();    readdirplus3res *nfsres = sbp->Xtmpl getres<readdirplus3res> ();  rpc_clear (*nfsres);  nfsres->set_status (NFS3_OK);  nfsres->resok->dir_attributes.set_present (true);  *nfsres->resok->dir_attributes.attributes = ro2nfsattr (dirdata->inode);    size_t off = readdirop->cookie;    sfsro_dirent *roe = dir->entries;  uint32 i = 0;  while (roe) {    roe = roe->nextentry;    i++;  }  uint32 n = MIN(i, readdirop->maxcount);  roe = dir->entries;  rpc_ptr<entryplus3> *last = &(nfsres->resok->reply.entries);  for (uint32 j = 0; j < n; j++) {    (*last).alloc ();    assert (0);    //fh2fileid (&roe->fh, &(*last)->fileid); // XXX broken    (*last)->name = roe->name;        // XXX Make LINUX happy    off +=  sizeof ((*last)->fileid) + roe->name.len();    if (j + 1 >= n) (*last)->cookie = INT64 (0x400ffffffff);    else (*last)->cookie = off;    (*last)->name_attributes.set_present(0);    (*last)->name_handle.set_present(0);    last = &(*last)->nextentry;    roe = roe->nextentry;  }  nfsres->resok->reply.eof = (i < n) ? 0 : 1;  sbp->reply (nfsres);}voidchord_server::read_inode_cb (nfscall *sbp, chordID ID, ptr<sfsro_data> data){  read3args *ra = sbp->Xtmpl getarg<read3args> ();  if (!data)     sbp->error (NFS3ERR_STALE);  else if (data->type != SFSRO_INODE)     sbp->error (NFS3ERR_IO);  else if (data->inode->type != SFSROREG && data->inode->type != SFSROREG_EXEC) {    sbp->error (NFS3ERR_IO);  }  else if (ra->offset >= data->inode->reg->size) {    read3res nfsres(NFS3_OK);    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -