"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/coda-src/resolution/resutil.cc" (17 Dec 2007, 10466 Bytes) of package /linux/misc/old/coda-6.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "resutil.cc" see the Fossies "Dox" file reference documentation.

    1 /* BLURB gpl
    2 
    3                            Coda File System
    4                               Release 6
    5 
    6           Copyright (c) 1987-2003 Carnegie Mellon University
    7                   Additional copyrights listed below
    8 
    9 This  code  is  distributed "AS IS" without warranty of any kind under
   10 the terms of the GNU General Public Licence Version 2, as shown in the
   11 file  LICENSE.  The  technical and financial  contributors to Coda are
   12 listed in the file CREDITS.
   13 
   14                         Additional copyrights
   15                            none currently
   16 
   17 #*/
   18 
   19 #ifdef __cplusplus
   20 extern "C" {
   21 #endif
   22 
   23 #ifdef HAVE_CONFIG_H
   24 #include <config.h>
   25 #endif
   26 
   27 #include <sys/types.h>
   28 #include <sys/time.h>
   29 #include <sys/stat.h>
   30 #include "coda_string.h"
   31 
   32 #include <netinet/in.h>
   33 #include "coda_assert.h"
   34 #include <stdio.h>
   35 #include <rpc2/rpc2.h>
   36 #include <rpc2/errors.h>
   37 #include <util.h>
   38 #include <rvmlib.h>
   39 
   40 #ifdef __cplusplus
   41 }
   42 #endif
   43 
   44 #include <srv.h>
   45 #include <codadir.h>
   46 #include <res.h>
   47 #include <vrdb.h>
   48 #include <volume.h>
   49 #include <lockqueue.h>
   50 
   51 #include "rescomm.h"
   52 #include "resutil.h"
   53 
   54 he *FindHE(olist *list, long hostaddress) {
   55     olist_iterator next(*list);
   56     he *h;
   57     while ( (h = (he *)next())) {
   58     if (h->hid == hostaddress)
   59         return(h);
   60     }
   61     return(0);
   62 }
   63 
   64 long RS_NewConnection(RPC2_Handle RPCid, RPC2_Integer set, 
   65               RPC2_Integer sl, RPC2_Integer et, 
   66               RPC2_Integer at, RPC2_CountedBS *cid)
   67 {
   68     conninfo *cip = new conninfo(RPCid, sl);
   69     conninfo::CInfoTab->insert(&cip->tblhandle);
   70     conninfo::ncinfos++;
   71     return(0);
   72 }
   73 
   74 /* Mark an object inconsistent */
   75 long RS_MarkInc(RPC2_Handle RPCid, ViceFid *Fid) 
   76 {
   77     Volume *volptr = 0;
   78     Vnode *vptr = 0;
   79     int errorcode = 0;
   80     rvm_return_t status = RVM_SUCCESS;
   81     
   82     SLog(9,  "ResMarkInc: Fid = (%x.%x.%x)", FID_(Fid));
   83     /* Fetch the object and mark inconsistent */
   84     if (!XlateVid(&Fid->Volume)){
   85     SLog(0,  "ResMarkInc: XlateVid(%x) failed", Fid->Volume);
   86     errorcode = EINVAL;
   87     goto FreeLocks;
   88     }
   89     SLog(9,  "ResMarkInc: Going to Fetch Object");
   90     errorcode = GetFsObj((ViceFid*)Fid, &volptr, &vptr, 
   91              WRITE_LOCK, NO_LOCK, 0, 0, 0);
   92     if (errorcode) goto FreeLocks;
   93     /* Should be checking if the volume is locked by the coordinator */
   94     /* Force Inconsistency for now */
   95     SLog(9,  "ResMarkInc: Marking object inconsistent");
   96     SetIncon(vptr->disk.versionvector);
   97 
   98 FreeLocks:
   99     rvmlib_begin_transaction(restore);
  100     SLog(9,  "ResMarkInc: Putting back vnode and volume");
  101     if (vptr){
  102     Error fileCode = 0;
  103     VPutVnode(&fileCode, vptr);
  104     CODA_ASSERT(fileCode == 0);
  105     }
  106     PutVolObj(&volptr, NO_LOCK);
  107     rvmlib_end_transaction(flush, &(status));
  108     SLog(2,  "ResMarkInc returns code %d", errorcode);
  109     return(errorcode);
  110 }
  111 
  112 extern unsigned long VMCounter;
  113 extern unsigned long startuptime;
  114 
  115 void AllocStoreId(ViceStoreId *s) {
  116     s->Host = ThisHostAddr;
  117     s->Uniquifier = startuptime + VMCounter;
  118     VMCounter++;
  119 }
  120 
  121 /* check for return codes other than time outs */
  122 long CheckRetCodes(RPC2_Integer *rc, unsigned long *rh, 
  123             unsigned long *hosts) {
  124     struct in_addr addr;
  125     long error = 0;
  126     for (int i = 0; i < VSG_MEMBERS; i++){
  127     hosts[i] = rh[i];
  128     if (rc[i] == ETIMEDOUT) hosts[i] = 0;
  129     if (rh[i] && rc[i] && rc[i] != ETIMEDOUT){
  130         /* non rpc error - drop this host too */
  131         hosts[i] = 0;
  132         error = rc[i];
  133         addr.s_addr = htonl(rh[i]);
  134         SLog(0,  "CheckRetCodes - an accessible server returned an error (server %s error %d)",
  135            inet_ntoa(addr), rc[i]);
  136     }
  137     }
  138     return(error);
  139 }
  140 
  141 /* check for return codes for resolution other than timeouts:
  142 
  143    - hosts will hold the ip address of hosts that responded
  144    - result will be VNOVNODE if that was the only error
  145      returned by the available servers
  146    - result will hold the first error encountered if not VNOVNODE
  147 */
  148 
  149 long CheckResRetCodes(RPC2_Integer *rc, unsigned long *rh, 
  150               unsigned long *hosts) 
  151 {
  152     struct in_addr addr;
  153     long error = 0, result = 0;
  154 
  155     for (int i = 0; i < VSG_MEMBERS; i++) {
  156         hosts[i] = rh[i];
  157         if (rc[i] == ETIMEDOUT) 
  158             hosts[i] = 0;
  159         if (rh[i] && rc[i] && rc[i] != ETIMEDOUT) {
  160             /* non rpc error - drop this host too
  161              * except if it has a runt. */
  162             if (rc[i] != VNOVNODE) hosts[i] = 0;
  163             error = rc[i];
  164             addr.s_addr = ntohl(rh[i]);
  165             SLog(0,  "CheckRetCodes: server %s returned error %d",
  166              inet_ntoa(addr), rc[i]);
  167         }
  168         if ( result == 0 || result == VNOVNODE )
  169             result = error;
  170     }
  171     return(result);
  172 }
  173 
  174 /**************** ilink class functions *******************/
  175 /* implmentation of functions that parse the list of inconsistencies 
  176  * at end of phase 1 during resolution and create a unique entry list
  177  */
  178 ilink *AddILE(dlist &dl, const char *name, long vnode, long unique, long pvnode,
  179           long punique, long type)
  180 {
  181     ilink *il = new ilink(name, vnode, unique, pvnode, punique, type);
  182     if (dl.IsMember(il)) {
  183     delete il;
  184     il = NULL;
  185     }
  186     else {
  187     SLog(39,  "AddILE: Adding new inc entry to dlist:");
  188     SLog(39,  "%s (%x.%x) child of (%x.%x),  type = %d",
  189         name, vnode, unique, pvnode, punique, type);
  190     dl.insert(il);  
  191     }
  192     return(il);
  193 }
  194 void BSToDlist(RPC2_BoundedBS *BS, dlist *dl) {
  195 
  196     char *beginc = (char *)BS->SeqBody;
  197     char *endc = ((char *)BS->SeqBody) + BS->SeqLen;
  198     
  199     while (beginc < endc) {
  200     char *name;
  201     long vnode, unique;
  202     long pvnode, punique;
  203     long type;
  204     ParseIncBSEntry(&beginc, &name, &vnode, &unique, &pvnode, &punique,&type);
  205     AddILE(*dl, name, vnode, unique, pvnode, punique, type);
  206     }
  207 }
  208 
  209 void DlistToBS(dlist *dl, RPC2_BoundedBS *BS) {
  210     BS->SeqLen = 0;
  211     ilink *il = 0;
  212     dlist_iterator next(*dl, DlAscending);
  213     while ((il = (ilink *)next())) {
  214     ViceFid Fid;
  215     ViceFid pFid;
  216     Fid.Volume = 0;
  217     Fid.Vnode = il->vnode;
  218     Fid.Unique = il->unique;
  219     pFid.Vnode = il->pvnode;
  220     pFid.Unique = il->punique;
  221     AllocIncBSEntry(BS, il->name, &Fid, &pFid, il->type);
  222     }
  223 }
  224 void CleanIncList(dlist *inclist) {
  225     ilink *il;
  226     if (inclist) {
  227     while ((il = (ilink *)inclist->get())) 
  228         delete il;
  229     delete inclist;
  230     }
  231 }
  232 
  233 void ParseIncBSEntry(char **c, char **name, long *vn, long *unique, 
  234              long *pvn, long *punique, long *type) {
  235     long *l = (long *)(*c);
  236     *c += sizeof(long);
  237     *vn = ntohl(*l);
  238     l = (long *)(*c);
  239     *unique = ntohl(*l);
  240     *c += sizeof(long);
  241     l = (long *)(*c);
  242     *pvn = ntohl(*l);
  243     *c += sizeof(long);
  244     l = (long *)(*c);
  245     *punique = ntohl(*l);
  246     *c += sizeof(long);
  247     l = (long *)*c;
  248     *type = ntohl(*l);
  249     *c += sizeof(long);
  250     *name = *c;
  251     int namelength = strlen(*c) + 1;
  252     int modlength = 0;
  253     if ((modlength = (namelength % sizeof(long)))) 
  254     namelength += sizeof(long) - modlength;
  255     *c += namelength;
  256 }
  257 /* AllocIncBSEntry
  258  *  Allocates the Piggy Back Entry if there is enough space in buffer 
  259  */
  260 void AllocIncBSEntry(RPC2_BoundedBS *bbs, char *name, ViceFid *Fid, 
  261              ViceFid *pFid, long type) {
  262     
  263     SLog(39,  "Allocating inc entry for:");
  264     SLog(39,  "Entry: %s (%x.%x) child of %x.%x type %d",
  265         name, Fid->Vnode, Fid->Unique, pFid->Vnode, pFid->Unique, type);
  266     char *c = ((char *)bbs->SeqBody) + bbs->SeqLen;
  267     int namelength = strlen(name) + 1;
  268     int modlength = 0;
  269     if ((modlength = (namelength % sizeof(long)))) 
  270     namelength += sizeof(long) - modlength;
  271     if (bbs->SeqLen + namelength + SIZEOF_INCFID > bbs->MaxSeqLen) {
  272     SLog(0,  "AllocIncPBEntry: NO MORE SPACE IN BUFFER");
  273     CODA_ASSERT(0);
  274     }
  275     long *l = (long *)c;
  276     *l = htonl(Fid->Vnode);
  277     l++;
  278     *l = htonl(Fid->Unique);
  279     l++;
  280     *l = htonl(pFid->Vnode);
  281     l++;
  282     *l = htonl(pFid->Unique);
  283     l++;
  284     *l = htonl(type);
  285     l++;
  286     c = (char *)l;
  287     strcpy(c, name);
  288     bbs->SeqLen += namelength + SIZEOF_INCFID;
  289 }
  290 
  291 int CompareIlinkEntry(ilink *i, ilink *j) {
  292     if (i->vnode < j->vnode) return(-1);
  293     if (i->vnode > j->vnode) return(1);
  294     if (i->unique < j->unique) return(-1);
  295     if (i->unique > j->unique) return(1);
  296     if (i->pvnode < j->pvnode) return(-1);
  297     if (i->pvnode > j->pvnode) return(1);
  298     if (i->punique < j->punique) return(-1);
  299     if (i->punique > j->punique) return(1);
  300     return(strcmp(i->name, j->name));
  301 }
  302 
  303 void ObtainResStatus(ResStatus *status, VnodeDiskObjectStruct *vdop)
  304 {
  305     status->status = 0;
  306     status->Author = vdop->author;
  307     status->Owner = vdop->owner;
  308     status->Date = vdop->unixModifyTime;
  309     status->Mode = vdop->modeBits;
  310 }
  311 
  312 void GetResStatus(unsigned long *succflags, ResStatus **status_p, 
  313           ViceStatus *finalstatus)
  314 {
  315     memset((void *)finalstatus, 0, sizeof(ViceStatus));
  316     int gotmbits = 0;
  317     for (int i = 0; i < VSG_MEMBERS; i++) {
  318     if (succflags[i]) {
  319         if (status_p[i]->Owner) {
  320         // a genuine (non-resolve generated) vnode
  321         if (!finalstatus->Owner) {
  322             finalstatus->Owner = status_p[i]->Owner;
  323             finalstatus->Author = status_p[i]->Author;
  324             finalstatus->Mode = status_p[i]->Mode;
  325             gotmbits = 1;
  326         }
  327         }
  328         // get the latest time && mode bits if not set already 
  329         if (status_p[i]->Date > finalstatus->Date) 
  330         finalstatus->Date = status_p[i]->Date;
  331         if (!gotmbits && status_p[i]->Mode) 
  332         finalstatus->Mode = status_p[i]->Mode;
  333     }
  334     }
  335 }
  336 
  337 /* Combine the directory contents and the ACL in a single blob.
  338  * Used during resolution to get the directory and ACL contents for
  339  * RS_FetchDirContents and RS_InstallVV. Don't forget to `free(buf)'! */
  340 void *Dir_n_ACL(struct Vnode *vptr, int *size)
  341 {
  342     char          *buf, *ptr;
  343     PDirHandle     dh;
  344     AL_AccessList *acl;
  345     int            dirsize, aclsize, quotasize = 0;
  346 
  347     dh      = VN_SetDirHandle(vptr);
  348     dirsize = DH_Length(dh);
  349 
  350     acl     = VVnodeACL(vptr);
  351     aclsize = VAclSize(vptr);
  352 
  353     if (vptr->vnodeNumber == 1 && vptr->disk.uniquifier == 1)
  354         quotasize = 2 * sizeof(int);
  355 
  356     ptr = buf = (char *)malloc(dirsize + aclsize + quotasize);
  357     if (!buf) {
  358         *size = 0;
  359         return NULL;
  360     }
  361 
  362     /* copy directory data */
  363     memcpy(ptr, DH_Data(dh), dirsize);
  364     ptr += dirsize;
  365 
  366     VN_PutDirHandle(vptr);
  367 
  368     /* copy acl */
  369     memset(ptr, 0, aclsize);
  370     memcpy(ptr, acl, acl->MySize);
  371     ptr += aclsize;
  372     SLog(9,"Dir_n_ACL: acl->MySize = %d acl->TotalNoOfEntries = %d\n",
  373          acl->MySize, acl->TotalNoOfEntries);
  374 
  375     /* copy volume quotas */
  376     if (quotasize) {
  377         *((int *)ptr) = htonl(V_maxquota(vptr->volumePtr));
  378         ptr += sizeof(int);
  379         *((int *)ptr) = htonl(V_minquota(vptr->volumePtr));
  380     }
  381 
  382     *size = dirsize + aclsize + quotasize;
  383 
  384     return (void *)buf;
  385 }
  386