"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/coda-src/venus/fso_cfscalls1.cc" (12 Feb 2007, 20952 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 "fso_cfscalls1.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               Copyright (c) 2002-2003 Intel Corporation
   16 
   17 #*/
   18 
   19 /*
   20  *
   21  *    CFS calls1.
   22  *
   23  *    ToDo:
   24  *       1. All mutating Vice calls should have the following IN arguments:
   25  *            NewSid, NewMutator (implicit from connection), NewMtime, 
   26  *            OldVV and DataVersion (for each object), NewStatus (for each object)
   27  */
   28 
   29 
   30 #ifdef __cplusplus
   31 extern "C" {
   32 #endif
   33 
   34 #include <stdio.h>
   35 #include <sys/types.h>
   36 #include <sys/file.h>
   37 
   38 #include <rpc2/rpc2.h>
   39 /* interfaces */
   40 #include <vice.h>
   41 
   42 #ifdef __cplusplus
   43 }
   44 #endif
   45 
   46 
   47 #include "comm.h"
   48 #include "fso.h"
   49 #include "mariner.h"
   50 #include "mgrp.h"
   51 #include "venuscb.h"
   52 #include "venus.private.h"
   53 #include "venusrecov.h"
   54 #include "venusvol.h"
   55 #include "vproc.h"
   56 #include "worker.h"
   57 
   58 
   59 /*  *****  Remove  *****  */
   60 
   61 /* MUST be called from within transaction! */
   62 void fsobj::LocalRemove(Date_t Mtime, char *name, fsobj *target_fso) {
   63     /* Update parent status. */
   64     {
   65     /* Delete the target name from the directory. */
   66     dir_Delete(name);
   67 
   68     /* Update the status to reflect the delete. */
   69     RVMLIB_REC_OBJECT(stat);
   70     stat.DataVersion++;
   71     stat.Length = dir_Length();
   72     stat.Date = Mtime;
   73     }
   74 
   75     /* Update the target status. */
   76     {
   77     RVMLIB_REC_OBJECT(target_fso->stat);
   78     target_fso->stat.LinkCount--;
   79     if (target_fso->stat.LinkCount == 0) {
   80         UpdateCacheStats(&FSDB->FileAttrStats, REMOVE,
   81                  NBLOCKS(sizeof(fsobj)));
   82         UpdateCacheStats(&FSDB->FileDataStats, REMOVE,
   83                  BLOCKS(target_fso));
   84         target_fso->Kill();
   85     }
   86     else {
   87         target_fso->stat.DataVersion++;
   88         target_fso->DetachHdbBindings();
   89     }
   90     }
   91 }
   92 
   93 
   94 /* local-repair modification */
   95 int fsobj::DisconnectedRemove(Date_t Mtime, uid_t uid, char *name,
   96                   fsobj *target_fso, int prepend)
   97 {
   98     int code = 0;
   99     repvol *rv;
  100 
  101     if (!vol->IsReplicated())
  102     return ETIMEDOUT;
  103     rv = (repvol *)vol;
  104 
  105     Recov_BeginTrans();
  106     code = rv->LogRemove(Mtime, uid, &fid, name, &target_fso->fid,
  107              target_fso->stat.LinkCount, prepend);
  108 
  109     if (code == 0 && prepend == 0)
  110         /* This MUST update second-class state! */
  111             /* It's already been updated if we're 'prepending',
  112          * which basically means it is a repair-related operation,
  113          * and doing it again would trigger an assertion. */
  114         LocalRemove(Mtime, name, target_fso);
  115     Recov_EndTrans(DMFP);
  116 
  117     return(code);
  118 }
  119 
  120 
  121 /* local-repair modification */
  122 int fsobj::Remove(char *name, fsobj *target_fso, uid_t uid)
  123 {
  124     LOG(10, ("fsobj::Remove: (%s, %s), uid = %d\n", GetComp(), name, uid));
  125 
  126     int code = 0;
  127     Date_t Mtime = Vtime();
  128 
  129     code = DisconnectedRemove(Mtime, uid, name, target_fso);
  130 
  131     if (code != 0) {
  132     Demote();
  133     target_fso->Demote();
  134     }
  135     return(code);
  136 }
  137 
  138 
  139 /*  *****  Link  *****  */
  140 
  141 /* MUST be called from within transaction! */
  142 void fsobj::LocalLink(Date_t Mtime, char *name, fsobj *source_fso) {
  143     /* Update parent status. */
  144     {
  145     /* Add the new <name, fid> to the directory. */
  146     dir_Create(name, &source_fso->fid);
  147 
  148     /* Update the status to reflect the create. */
  149     RVMLIB_REC_OBJECT(stat);
  150     stat.DataVersion++;
  151     stat.Length = dir_Length();
  152     stat.Date = Mtime;
  153     if (source_fso->IsDir())
  154         stat.LinkCount++;
  155     DemoteHdbBindings();        /* in case an expansion would now be satisfied! */
  156     }
  157 
  158     /* Update source status. */
  159     {
  160     RVMLIB_REC_OBJECT(source_fso->stat);
  161 /*    source_fso->stat.DataVersion++;*/
  162     source_fso->stat.LinkCount++;
  163     }
  164 }
  165 
  166 
  167 /* local-repair modification */
  168 int fsobj::DisconnectedLink(Date_t Mtime, uid_t uid, char *name,
  169                 fsobj *source_fso, int prepend)
  170 {
  171     int code = 0;
  172     repvol *rv;
  173 
  174     if (!vol->IsReplicated())
  175     return ETIMEDOUT;
  176     rv = (repvol *)vol;
  177 
  178     Recov_BeginTrans();
  179     code = rv->LogLink(Mtime, uid, &fid, name, &source_fso->fid, prepend);
  180     
  181     if (code == 0 && prepend == 0)
  182         /* This MUST update second-class state! */
  183             /* It's already been updated if we're 'prepending',
  184          * which basically means it is a repair-related operation,
  185          * and doing it again would trigger an assertion. */
  186         LocalLink(Mtime, name, source_fso);
  187     Recov_EndTrans(DMFP);
  188 
  189     return(code);
  190 }
  191 
  192 
  193 /* local-repair modification */
  194 int fsobj::Link(char *name, fsobj *source_fso, uid_t uid)
  195 {
  196     LOG(10, ("fsobj::Link: (%s/%s, %s), uid = %d\n",
  197           GetComp(), source_fso->comp, name, uid));
  198 
  199     int code = 0;
  200     Date_t Mtime = Vtime();
  201 
  202     code = DisconnectedLink(Mtime, uid, name, source_fso);
  203 
  204     if (code != 0) {
  205     Demote();
  206     source_fso->Demote();
  207     }
  208     return(code);
  209 }
  210 
  211 
  212 /*  *****  Rename  *****  */
  213 
  214 /* MUST be called from within transaction! */
  215 void fsobj::LocalRename(Date_t Mtime, fsobj *s_parent_fso, char *s_name,
  216              fsobj *s_fso, char *t_name, fsobj *t_fso) {
  217     int SameParent = (s_parent_fso == this);
  218     int TargetExists = (t_fso != 0);
  219 
  220     /* Update local status. */
  221     {
  222     RVMLIB_REC_OBJECT(stat);
  223     if (!SameParent)
  224         RVMLIB_REC_OBJECT(s_parent_fso->stat);
  225     RVMLIB_REC_OBJECT(s_fso->stat);
  226     if (TargetExists)
  227         RVMLIB_REC_OBJECT(t_fso->stat);
  228 
  229     /*Remove the source <name, fid> from its directory. */
  230     s_parent_fso->dir_Delete(s_name);
  231 
  232     /* Remove the target <name, fid> from its directory (if it exists). */
  233     if (TargetExists) {
  234         dir_Delete(t_name);
  235 
  236         t_fso->DetachHdbBindings();
  237         if (t_fso->IsDir()) {
  238         stat.LinkCount--;
  239 
  240         /* Delete the target object. */
  241         UpdateCacheStats(&FSDB->DirAttrStats, REMOVE,
  242                  NBLOCKS(sizeof(fsobj)));
  243         UpdateCacheStats(&FSDB->DirDataStats, REMOVE,
  244                  BLOCKS(t_fso));
  245         t_fso->Kill();
  246         }
  247         else {
  248         /* Update the target status. */
  249         t_fso->stat.LinkCount--;
  250         if (t_fso->stat.LinkCount == 0) {
  251             UpdateCacheStats(&FSDB->FileAttrStats, REMOVE,
  252                      NBLOCKS(sizeof(fsobj)));
  253             UpdateCacheStats(&FSDB->FileDataStats, REMOVE,
  254                      BLOCKS(t_fso));
  255             t_fso->Kill();
  256         }
  257         else {
  258             t_fso->stat.DataVersion++;
  259         }
  260         }
  261     }
  262 
  263     /* Create the target <name, fid> in the target directory. */
  264     dir_Create(t_name, &s_fso->fid);
  265 
  266     /* Alter ".." entry in source if necessary. */
  267     if (!SameParent && s_fso->IsDir()) {
  268         s_fso->dir_Delete("..");
  269         s_parent_fso->stat.LinkCount--;
  270         s_fso->dir_Create("..", &fid);
  271         stat.LinkCount++;
  272     }
  273 
  274     /* Update parents' status to reflect the create(s) and delete(s). */
  275     stat.DataVersion++;
  276     stat.Length = dir_Length();
  277     stat.Date = Mtime;
  278     if (SameParent) {
  279         DemoteHdbBindings();        /* in case an expansion would now be satisfied! */
  280     }
  281     else {
  282         s_parent_fso->stat.DataVersion++;
  283         s_parent_fso->stat.Length = s_parent_fso->dir_Length();
  284         s_parent_fso->stat.Date = Mtime;
  285     }
  286 
  287     /* Update the source status to reflect the rename and possible create/delete. */
  288     if (t_name && !STREQ(s_fso->comp, t_name))
  289         s_fso->SetComp(t_name);
  290     s_fso->DetachHdbBindings();
  291 /*    s_fso->stat.DataVersion++;*/
  292     if (!SameParent)
  293         s_fso->SetParent(fid.Vnode, fid.Unique);
  294     }
  295 }
  296 
  297 
  298 /* local-repair modification */
  299 int fsobj::DisconnectedRename(Date_t Mtime, uid_t uid, fsobj *s_parent_fso,
  300                   char *s_name, fsobj *s_fso, char *t_name,
  301                   fsobj *t_fso, int prepend)
  302 {
  303     int code = 0;
  304     int TargetExists = (t_fso != 0);
  305     repvol *rv;
  306 
  307     if (!vol->IsReplicated())
  308     return ETIMEDOUT;
  309     rv = (repvol *)vol;
  310 
  311     Recov_BeginTrans();
  312     code = rv->LogRename(Mtime, uid, &s_parent_fso->fid, s_name, &fid, t_name,
  313              &s_fso->fid, (TargetExists ? &t_fso->fid : &NullFid),
  314              (TargetExists ? t_fso->stat.LinkCount:0), prepend);
  315 
  316     if (code == 0 && prepend == 0)
  317         /* This MUST update second-class state! */
  318             /* It's already been updated if we're 'prepending',
  319          * which basically means it is a repair-related operation,
  320          * and doing it again would trigger an assertion. */
  321         LocalRename(Mtime, s_parent_fso, s_name, s_fso, t_name, t_fso);
  322     Recov_EndTrans(DMFP);
  323 
  324     return(code);
  325 }
  326 
  327 
  328 /* local-repair modification */
  329 int fsobj::Rename(fsobj *s_parent_fso, char *s_name, fsobj *s_fso,
  330            char *t_name, fsobj *t_fso, uid_t uid)
  331 {
  332     LOG(10, ("fsobj::Rename : (%s/%s, %s/%s), uid = %d\n",
  333           (s_parent_fso ? s_parent_fso->GetComp() : GetComp()),
  334           s_name, GetComp(), t_name, uid));
  335 
  336     int code = 0;
  337     Date_t Mtime = Vtime();
  338     int SameParent = (s_parent_fso == 0);
  339     if (SameParent) s_parent_fso = this;
  340     int TargetExists = (t_fso != 0);
  341 
  342     code = DisconnectedRename(Mtime, uid, s_parent_fso, s_name, s_fso,
  343                   t_name, t_fso);
  344 
  345     if (code != 0) {
  346     Demote();
  347     if (!SameParent) s_parent_fso->Demote();
  348     s_fso->Demote();
  349     if (TargetExists) t_fso->Demote();
  350     }
  351     return(code);
  352 }
  353 
  354 
  355 /*  *****  Mkdir  *****  */
  356 
  357 /* MUST be called from within transaction! */
  358 void fsobj::LocalMkdir(Date_t Mtime, fsobj *target_fso, char *name,
  359             uid_t Owner, unsigned short Mode)
  360 {
  361     /* Update parent status. */
  362     {
  363     /* Add the new <name, fid> to the directory. */
  364     dir_Create(name, &target_fso->fid);
  365 
  366     /* Update the status to reflect the create. */
  367     RVMLIB_REC_OBJECT(stat);
  368     stat.DataVersion++;
  369     stat.Length = dir_Length();
  370     stat.Date = Mtime;
  371     stat.LinkCount++;
  372     }
  373 
  374     /* Set target status and data. */
  375     {
  376     /* What about ACL? -JJK */
  377     RVMLIB_REC_OBJECT(*target_fso);
  378     target_fso->stat.VnodeType = Directory;
  379     target_fso->stat.LinkCount = 2;
  380     target_fso->stat.Length = 0;
  381     target_fso->stat.DataVersion = 1;
  382     target_fso->stat.Date = Mtime;
  383     target_fso->stat.Owner = Owner;
  384     target_fso->stat.Mode = Mode;
  385     target_fso->AnyUser = AnyUser;
  386     memcpy(target_fso->SpecificUser, SpecificUser, (CPSIZE * sizeof(AcRights)));
  387     target_fso->SetParent(fid.Vnode, fid.Unique);
  388 
  389     /* Create the target directory. */
  390     target_fso->dir_MakeDir();
  391 
  392     target_fso->Matriculate();
  393     target_fso->Reference();
  394     target_fso->ComputePriority();
  395     }
  396 }
  397 
  398 
  399 /* local-repair modification */
  400 int fsobj::DisconnectedMkdir(Date_t Mtime, uid_t uid, fsobj **t_fso_addr,
  401                  char *name, unsigned short Mode, int target_pri,
  402                  int prepend)
  403 {
  404     int code = 0;
  405     fsobj *target_fso = 0;
  406     VenusFid target_fid;
  407     RPC2_Unsigned AllocHost = 0;
  408     repvol *rv;
  409 
  410     if (!vol->IsReplicated()) {
  411     code = ETIMEDOUT;
  412     goto Exit;
  413     }
  414     rv = (repvol *)vol;
  415 
  416     /* Allocate a fid for the new object. */
  417     /* if we time out, return so we will try again with a local fid. */
  418     code = rv->AllocFid(Directory, &target_fid, &AllocHost, uid);
  419     if (code != 0) goto Exit;
  420 
  421     /* Allocate the fsobj. */
  422     target_fso = FSDB->Create(&target_fid, target_pri, name, &fid);
  423     if (target_fso == 0) {
  424     UpdateCacheStats(&FSDB->DirAttrStats, NOSPACE,
  425              NBLOCKS(sizeof(fsobj)));
  426     code = ENOSPC;
  427     goto Exit;
  428     }
  429     UpdateCacheStats(&FSDB->DirAttrStats, CREATE,
  430               NBLOCKS(sizeof(fsobj)));
  431 
  432     Recov_BeginTrans();
  433     code = rv->LogMkdir(Mtime, uid, &fid, name, &target_fso->fid, Mode,
  434             prepend);
  435 
  436     if (code == 0 && prepend == 0) {
  437         /* This MUST update second-class state! */
  438             /* It's already been updated if we're 'prepending',
  439          * which basically means it is a repair-related operation,
  440          * and doing it again would trigger an assertion. */
  441         LocalMkdir(Mtime, target_fso, name, uid, Mode);
  442 
  443         /* target_fso->stat is not initialized until LocalMkdir */
  444         RVMLIB_REC_OBJECT(target_fso->CleanStat);
  445         target_fso->CleanStat.Length = target_fso->stat.Length;
  446         target_fso->CleanStat.Date = target_fso->stat.Date;
  447        }
  448     Recov_EndTrans(DMFP);
  449 
  450 Exit:
  451     if (code == 0) {
  452     *t_fso_addr = target_fso;
  453     }
  454     else {
  455     if (target_fso != 0) {
  456         FSO_ASSERT(target_fso, !HAVESTATUS(target_fso));
  457         Recov_BeginTrans();
  458         target_fso->Kill();
  459         Recov_EndTrans(DMFP);
  460         FSDB->Put(&target_fso);
  461     }
  462     }
  463     return(code);
  464 }
  465 
  466 
  467 /* local-repair modification */
  468 /* Returns target object write-locked (on success). */
  469 int fsobj::Mkdir(char *name, fsobj **target_fso_addr,
  470           uid_t uid, unsigned short Mode, int target_pri)
  471 {
  472     LOG(10, ("fsobj::Mkdir: (%s, %s, %d), uid = %d\n",
  473           GetComp(), name, target_pri, uid));
  474 
  475     int code = 0;
  476     Date_t Mtime = Vtime();
  477     *target_fso_addr = 0;
  478 
  479     code = DisconnectedMkdir(Mtime, uid, target_fso_addr,
  480                  name, Mode, target_pri);
  481 
  482     if (code != 0) {
  483     Demote();
  484     }
  485     return(code);
  486 }
  487 
  488 
  489 /*  *****  Rmdir  *****  */
  490 
  491 /* MUST be called from within transaction! */
  492 void fsobj::LocalRmdir(Date_t Mtime, char *name, fsobj *target_fso) {
  493     /* Update parent status. */
  494     {
  495     /* Delete the target name from the directory.. */
  496     dir_Delete(name);
  497 
  498     /* Update the status to reflect the delete. */
  499     RVMLIB_REC_OBJECT(stat);
  500     stat.DataVersion++;
  501     stat.Length = dir_Length();
  502     stat.Date = Mtime;
  503     stat.LinkCount--;
  504     }
  505 
  506     /* Update target status. */
  507     {
  508     /* Delete the target object. */
  509     RVMLIB_REC_OBJECT(target_fso->stat);
  510     target_fso->stat.LinkCount--;
  511     target_fso->DetachHdbBindings();
  512     UpdateCacheStats(&FSDB->DirAttrStats, REMOVE,
  513              NBLOCKS(sizeof(fsobj)));
  514     UpdateCacheStats(&FSDB->DirDataStats, REMOVE,
  515              BLOCKS(target_fso));
  516     target_fso->Kill();
  517     }
  518 }
  519 
  520 
  521 /* local-repair modification */
  522 int fsobj::DisconnectedRmdir(Date_t Mtime, uid_t uid, char *name,
  523                  fsobj *target_fso, int prepend)
  524 {
  525     int code = 0;
  526     repvol *rv;
  527 
  528     if (!vol->IsReplicated())
  529     return ETIMEDOUT;
  530     rv = (repvol *)vol;
  531 
  532     Recov_BeginTrans();
  533     code = rv->LogRmdir(Mtime, uid, &fid, name, &target_fso->fid, prepend);
  534 
  535     if (code == 0 && prepend == 0)
  536         /* This MUST update second-class state! */
  537             /* It's already been updated if we're 'prepending',
  538          * which basically means it is a repair-related operation,
  539          * and doing it again would trigger an assertion. */
  540         LocalRmdir(Mtime, name, target_fso);
  541     Recov_EndTrans(DMFP);
  542 
  543     return(code);
  544 }
  545 
  546 
  547 /* local-repair modification */
  548 int fsobj::Rmdir(char *name, fsobj *target_fso, uid_t uid)
  549 {
  550     LOG(10, ("fsobj::Rmdir: (%s, %s), uid = %d\n", GetComp(), name, uid));
  551 
  552     int code = 0;
  553     Date_t Mtime = Vtime();
  554 
  555     code = DisconnectedRmdir(Mtime, uid, name, target_fso);
  556 
  557     if (code != 0) {
  558     Demote();
  559     target_fso->Demote();
  560     }
  561     return(code);
  562 }
  563 
  564 
  565 /*  *****  Symlink  *****  */
  566 
  567 /* MUST be called from within transaction! */
  568 void fsobj::LocalSymlink(Date_t Mtime, fsobj *target_fso, char *name,
  569               char *contents, uid_t Owner, unsigned short Mode)
  570 {
  571     /* Update parent status. */
  572     {
  573     /* Add the new <name, fid> to the directory. */
  574     dir_Create(name, &target_fso->fid);
  575 
  576     /* Update the status to reflect the create. */
  577     RVMLIB_REC_OBJECT(stat);
  578     stat.DataVersion++;
  579     stat.Length = dir_Length();
  580     stat.Date = Mtime;
  581     }
  582 
  583     /* Set target status. */
  584     {
  585     /* Initialize the target fsobj. */
  586     RVMLIB_REC_OBJECT(*target_fso);
  587     target_fso->stat.VnodeType = SymbolicLink;
  588     target_fso->stat.LinkCount = 1;
  589     target_fso->stat.Length = 0;
  590     target_fso->stat.DataVersion = 1;
  591     target_fso->stat.Date = Mtime;
  592     target_fso->stat.Owner = Owner;
  593     target_fso->stat.Mode = Mode;
  594     target_fso->Matriculate();
  595     target_fso->SetParent(fid.Vnode, fid.Unique);
  596 
  597     /* Write out the link contents. */
  598     int linklen = (int) strlen(contents);
  599     target_fso->stat.Length = linklen;
  600     target_fso->data.symlink = (char *)rvmlib_rec_malloc(linklen + 1);
  601     rvmlib_set_range(target_fso->data.symlink, linklen);
  602     memcpy(target_fso->data.symlink, contents, linklen);
  603     UpdateCacheStats(&FSDB->FileDataStats, CREATE,
  604              NBLOCKS(linklen));
  605 
  606     target_fso->Reference();
  607     target_fso->ComputePriority();
  608     }
  609 }
  610 
  611 
  612 /* local-repair modification */
  613 int fsobj::DisconnectedSymlink(Date_t Mtime, uid_t uid, fsobj **t_fso_addr,
  614                    char *name, char *contents, unsigned short Mode,
  615                    int target_pri, int prepend)
  616 {
  617     int code = 0;
  618     fsobj *target_fso = 0;
  619     VenusFid target_fid = NullFid;
  620     RPC2_Unsigned AllocHost = 0;
  621     repvol *rv;
  622 
  623     if (!vol->IsReplicated()) {
  624     code = ETIMEDOUT;
  625     goto Exit;
  626     }
  627     rv = (repvol *)vol;
  628     
  629     /* Allocate a fid for the new object. */
  630     /* if we time out, return so we will try again with a local fid. */
  631     code = rv->AllocFid(SymbolicLink, &target_fid, &AllocHost, uid);
  632     if (code != 0) goto Exit;
  633 
  634     /* Allocate the fsobj. */
  635     target_fso = FSDB->Create(&target_fid, target_pri, name, &fid);
  636     if (target_fso == 0) {
  637     UpdateCacheStats(&FSDB->FileAttrStats, NOSPACE,
  638              NBLOCKS(sizeof(fsobj)));
  639     code = ENOSPC;
  640     goto Exit;
  641     }
  642     UpdateCacheStats(&FSDB->FileAttrStats, CREATE,
  643               NBLOCKS(sizeof(fsobj)));
  644 
  645     Recov_BeginTrans();
  646     code = rv->LogSymlink(Mtime, uid, &fid, name, contents, &target_fso->fid,
  647               Mode, prepend);
  648     
  649     if (code == 0 && prepend == 0) {
  650         /* This MUST update second-class state! */
  651             /* It's already been updated if we're 'prepending',
  652          * which basically means it is a repair-related operation,
  653          * and doing it again would trigger an assertion. */
  654         LocalSymlink(Mtime, target_fso, name, contents, uid, Mode);
  655 
  656         /* target_fso->stat is not initialized until LocalSymlink */
  657         RVMLIB_REC_OBJECT(target_fso->CleanStat);
  658         target_fso->CleanStat.Length = target_fso->stat.Length;
  659         target_fso->CleanStat.Date = target_fso->stat.Date;
  660        }
  661     Recov_EndTrans(DMFP);
  662 
  663 Exit:
  664     if (code == 0) {
  665     *t_fso_addr = target_fso;
  666     }
  667     else {
  668     if (target_fso != 0) {
  669         FSO_ASSERT(target_fso, !HAVESTATUS(target_fso));
  670         Recov_BeginTrans();
  671         target_fso->Kill();
  672         Recov_EndTrans(DMFP);
  673         FSDB->Put(&target_fso);
  674     }
  675     }
  676     return(code);
  677 }
  678 
  679 
  680 /* local-repair modification */
  681 int fsobj::Symlink(char *s_name, char *t_name, uid_t uid, unsigned short Mode,
  682            int target_pri)
  683 {
  684     LOG(10, ("fsobj::Symlink: (%s, %s, %s, %d), uid = %d\n",
  685           GetComp(), s_name, t_name, target_pri, uid));
  686 
  687     int code = 0;
  688     Date_t Mtime = Vtime();
  689     fsobj *target_fso = 0;
  690 
  691     code = DisconnectedSymlink(Mtime, uid, &target_fso, t_name, s_name,
  692                    Mode, target_pri);
  693 
  694     if (code == 0) {
  695     /* Target is NOT an OUT parameter. */
  696     FSDB->Put(&target_fso);
  697     }
  698     else {
  699     Demote();
  700     }
  701     return(code);
  702 }
  703 
  704 
  705 /*  *****  SetVV  *****  */
  706 
  707 /* This should eventually disappear to be a side-effect of the Repair call! -JJK */
  708 /* Call with object write-locked. */
  709 int fsobj::SetVV(ViceVersionVector *newvv, uid_t uid)
  710 {
  711     LOG(10, ("fsobj::SetVV: (%s), uid = %d\n",
  712           GetComp(), uid));
  713 
  714     int code = 0;
  715 
  716     /* This is a connected-mode only routine! */
  717     if (!REACHABLE(this))
  718     return ETIMEDOUT;
  719 
  720     /* COP2 Piggybacking. */
  721     char PiggyData[COP2SIZE];
  722     RPC2_CountedBS PiggyBS;
  723     PiggyBS.SeqLen = 0;
  724     PiggyBS.SeqBody = (RPC2_ByteSeq)PiggyData;
  725 
  726     if (vol->IsReplicated()) {
  727     mgrpent *m = 0;
  728     repvol *vp = (repvol *)vol;
  729 
  730     /* Acquire an Mgroup. */
  731     code = vp->GetMgrp(&m, uid, (PIGGYCOP2 ? &PiggyBS : 0));
  732     if (code != 0) goto RepExit;
  733 
  734     /* The SetVV call. */
  735     {
  736         /* Make the RPC call. */
  737         CFSOP_PRELUDE("store::SetVV %-30s\n", comp, fid);
  738         MULTI_START_MESSAGE(ViceSetVV_OP);
  739         code = (int) MRPC_MakeMulti(ViceSetVV_OP, ViceSetVV_PTR,
  740                     VSG_MEMBERS, m->rocc.handles,
  741                     m->rocc.retcodes, m->rocc.MIp, 0, 0,
  742                     MakeViceFid(&fid), newvv, &PiggyBS);
  743         MULTI_END_MESSAGE(ViceSetVV_OP);
  744         CFSOP_POSTLUDE("store::setvv done\n");
  745 
  746         /* Collate responses from individual servers and decide what to do next. */
  747         code = vp->Collate_COP2(m, code);
  748         MULTI_RECORD_STATS(ViceSetVV_OP);
  749         if (code != 0) goto RepExit;
  750 
  751         /* Finalize COP2 Piggybacking. */
  752         if (PIGGYCOP2)
  753         vp->ClearCOP2(&PiggyBS);
  754     }
  755 
  756     /* Do op locally. */
  757     Recov_BeginTrans();
  758     RVMLIB_REC_OBJECT(stat);
  759     stat.VV = *newvv;
  760     Recov_EndTrans(CMFP);
  761 
  762 RepExit:
  763     if (m) m->Put();
  764     switch(code) {
  765     case 0:
  766         break;
  767 
  768     case ETIMEDOUT:
  769         code = ERETRY;
  770         break;
  771 
  772     case ESYNRESOLVE:
  773     case EINCONS:
  774         CHOKE("fsobj::SetVV: code = %d", code);
  775         break;
  776 
  777     default:
  778         break;
  779     }
  780     }
  781     else {
  782     /* Acquire a Connection. */
  783     connent *c;
  784     volrep *vp = (volrep *)vol;
  785     code = vp->GetConn(&c, uid);
  786     if (code != 0) goto NonRepExit;
  787 
  788     /* Make the RPC call. */
  789     CFSOP_PRELUDE("store::SetVV %-30s\n", comp, fid);
  790     UNI_START_MESSAGE(ViceSetVV_OP);
  791     code = (int) ViceSetVV(c->connid, MakeViceFid(&fid), newvv, &PiggyBS);
  792     UNI_END_MESSAGE(ViceSetVV_OP);
  793     CFSOP_POSTLUDE("store::setvv done\n");
  794 
  795     /* Examine the return code to decide what to do next. */
  796     code = vp->Collate(c, code);
  797     UNI_RECORD_STATS(ViceSetVV_OP);
  798     if (code != 0) goto NonRepExit;
  799 
  800     /* Do op locally. */
  801     Recov_BeginTrans();
  802     RVMLIB_REC_OBJECT(stat);
  803     stat.VV = *newvv;
  804     Recov_EndTrans(CMFP);
  805 
  806 NonRepExit:
  807     PutConn(&c);
  808     }
  809 
  810     /* Replica control rights are invalid in any case. */
  811     Demote();
  812 
  813     LOG(0, ("MARIA:  We just SetVV'd.\n"));
  814 
  815     return(code);
  816 }