dread-do-validation-20041012
[openafs.git] / src / afs / VNOPS / afs_vnop_link.c
index 8c6da83..22ac2bc 100644 (file)
  *
  */
 
-#include "../afs/param.h"      /* Should be always first */
 #include <afsconfig.h>
+#include "afs/param.h"
 
-RCSID("$Header$");
+RCSID
+    ("$Header$");
 
-#include "../afs/sysincludes.h"        /* Standard vendor system headers */
-#include "../afs/afsincludes.h"        /* Afs-based standard headers */
-#include "../afs/afs_stats.h" /* statistics */
-#include "../afs/afs_cbqueue.h"
-#include "../afs/nfsclient.h"
-#include "../afs/afs_osidnlc.h"
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afsincludes.h"       /* Afs-based standard headers */
+#include "afs/afs_stats.h"     /* statistics */
+#include "afs/afs_cbqueue.h"
+#include "afs/nfsclient.h"
+#include "afs/afs_osidnlc.h"
 
 extern afs_rwlock_t afs_xcbhash;
 
 /* Note that we don't set CDirty here, this is OK because the link
  * RPC is called synchronously. */
 
+int
 #ifdef AFS_OSF_ENV
 afs_link(avc, ndp)
-    register struct vcache *avc;
-    struct nameidata *ndp; {
-    register struct vcache *adp = (struct vcache *)ndp->ni_dvp;
+     struct vcache *avc;
+     struct nameidata *ndp;
+{
+    struct vcache *adp = VTOAFS(ndp->ni_dvp);
     char *aname = ndp->ni_dent.d_name;
     struct ucred *acred = ndp->ni_cred;
-#else  /* AFS_OSF_ENV */
+#else /* AFS_OSF_ENV */
 #if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
 afs_link(OSI_VC_ARG(adp), avc, aname, acred)
 #else
 afs_link(avc, OSI_VC_ARG(adp), aname, acred)
 #endif
-    OSI_VC_DECL(adp);
-    register struct vcache *avc;
-    char *aname;
-    struct AFS_UCRED *acred;
+     OSI_VC_DECL(adp);
+     struct vcache *avc;
+     char *aname;
+     struct AFS_UCRED *acred;
 {
 #endif
     struct vrequest treq;
     register struct dcache *tdc;
     register afs_int32 code;
     register struct conn *tc;
-    afs_int32 offset, len;
+    afs_size_t offset, len;
     struct AFSFetchStatus OutFidStatus, OutDirStatus;
     struct AFSVolSync tsync;
-    XSTATS_DECLS
-    OSI_VC_CONVERT(adp)
+    struct afs_fakestat_state vfakestate, dfakestate;
+    XSTATS_DECLS;
+    OSI_VC_CONVERT(adp);
 
     AFS_STATCNT(afs_link);
     afs_Trace3(afs_iclSetp, CM_TRACE_LINK, ICL_TYPE_POINTER, adp,
               ICL_TYPE_POINTER, avc, ICL_TYPE_STRING, aname);
     /* create a hard link; new entry is aname in dir adp */
-    if (code = afs_InitReq(&treq, acred)) return code;
-    if (avc->fid.Cell != adp->fid.Cell || avc->fid.Fid.Volume != adp->fid.Fid.Volume) {
+    if ((code = afs_InitReq(&treq, acred)))
+       goto done2;
+
+    afs_InitFakeStat(&vfakestate);
+    afs_InitFakeStat(&dfakestate);
+    code = afs_EvalFakeStat(&avc, &vfakestate, &treq);
+    if (code)
+       goto done;
+    code = afs_EvalFakeStat(&adp, &dfakestate, &treq);
+    if (code)
+       goto done;
+
+    if (avc->fid.Cell != adp->fid.Cell
+       || avc->fid.Fid.Volume != adp->fid.Fid.Volume) {
        code = EXDEV;
        goto done;
     }
+    if (strlen(aname) > AFSNAMEMAX) {
+       code = ENAMETOOLONG;
+       goto done;
+    }
     code = afs_VerifyVCache(adp, &treq);
-    if (code) goto done;
+    if (code)
+       goto done;
 
     /** If the volume is read-only, return error without making an RPC to the
       * fileserver
       */
-    if ( adp->states & CRO ) {
-        code = EROFS;
+    if (adp->states & CRO) {
+       code = EROFS;
        goto done;
     }
 
-    tdc        = afs_GetDCache(adp, 0, &treq, &offset, &len, 1);  /* test for error below */
-    ObtainWriteLock(&adp->lock,145);
+    tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
+    ObtainWriteLock(&adp->lock, 145);
     do {
        tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
        if (tc) {
-          XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_LINK);
-#ifdef RX_ENABLE_LOCKS
-         AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
-           code = RXAFS_Link(tc->id, (struct AFSFid *) &adp->fid.Fid, aname,
-                             (struct AFSFid *) &avc->fid.Fid, &OutFidStatus,
-                             &OutDirStatus, &tsync);
-#ifdef RX_ENABLE_LOCKS
-         AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
-          XSTATS_END_TIME;
+           XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_LINK);
+           RX_AFS_GUNLOCK();
+           code =
+               RXAFS_Link(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
+                          (struct AFSFid *)&avc->fid.Fid, &OutFidStatus,
+                          &OutDirStatus, &tsync);
+           RX_AFS_GLOCK();
+           XSTATS_END_TIME;
 
-       }
-       else code = -1;
-    } while
-      (afs_Analyze(tc, code, &adp->fid, &treq,
-                  AFS_STATS_FS_RPCIDX_LINK, SHARED_LOCK, (struct cell *)0));
+       } else
+           code = -1;
+    } while (afs_Analyze
+            (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_LINK,
+             SHARED_LOCK, NULL));
 
     if (code) {
-       if (tdc) afs_PutDCache(tdc);
+       if (tdc)
+           afs_PutDCache(tdc);
        if (code < 0) {
-         ObtainWriteLock(&afs_xcbhash, 492);
-         afs_DequeueCallback(adp);
-         adp->states &= ~CStatd;
-         ReleaseWriteLock(&afs_xcbhash);
-         osi_dnlc_purgedp(adp);
+           ObtainWriteLock(&afs_xcbhash, 492);
+           afs_DequeueCallback(adp);
+           adp->states &= ~CStatd;
+           ReleaseWriteLock(&afs_xcbhash);
+           osi_dnlc_purgedp(adp);
        }
        ReleaseWriteLock(&adp->lock);
        goto done;
     }
+    if (tdc)
+       ObtainWriteLock(&tdc->lock, 635);
     if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
        /* we can do it locally */
-       code = afs_dir_Create(&tdc->f.inode, aname, &avc->fid.Fid);
+       code = afs_dir_Create(&tdc->f, aname, &avc->fid.Fid);
        if (code) {
            ZapDCE(tdc);        /* surprise error -- invalid value */
-           DZap(&tdc->f.inode);
+           DZap(&tdc->f);
        }
     }
     if (tdc) {
+       ReleaseWriteLock(&tdc->lock);
        afs_PutDCache(tdc);     /* drop ref count */
     }
     ReleaseWriteLock(&adp->lock);
-    ObtainWriteLock(&avc->lock,146);    /* correct link count */
+    ObtainWriteLock(&avc->lock, 146);  /* correct link count */
 
     /* we could lock both dir and file; since we get the new fid
      * status back, you'd think we could put it in the cache status
@@ -137,16 +159,19 @@ afs_link(avc, OSI_VC_ARG(adp), aname, acred)
 
     ObtainWriteLock(&afs_xcbhash, 493);
     afs_DequeueCallback(avc);
-    avc->states        &= ~CStatd;     /* don't really know new link count */
+    avc->states &= ~CStatd;    /* don't really know new link count */
     ReleaseWriteLock(&afs_xcbhash);
     if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
        osi_dnlc_purgedp(avc);
     ReleaseWriteLock(&avc->lock);
     code = 0;
-done:
+  done:
+    code = afs_CheckCode(code, &treq, 24);
+    afs_PutFakeStat(&vfakestate);
+    afs_PutFakeStat(&dfakestate);
+  done2:
 #ifdef AFS_OSF_ENV
-    afs_PutVCache(adp, WRITE_LOCK);
-#endif /* AFS_OSF_ENV */
-    return afs_CheckCode(code, &treq);
+    afs_PutVCache(adp);
+#endif /* AFS_OSF_ENV */
+    return code;
 }
-