| File: | afs/VNOPS/afs_vnop_rename.c |
| Location: | line 310, column 6 |
| Description: | Assigned value is garbage or undefined |
| 1 | /* | ||
| 2 | * Copyright 2000, International Business Machines Corporation and others. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * This software has been released under the terms of the IBM Public | ||
| 6 | * License. For details, see the LICENSE file in the top-level source | ||
| 7 | * directory or online at http://www.openafs.org/dl/license10.html | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * Implements: | ||
| 12 | * afsrename | ||
| 13 | * afs_rename | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <afsconfig.h> | ||
| 18 | #include "afs/param.h" | ||
| 19 | |||
| 20 | |||
| 21 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | ||
| 22 | #include "afsincludes.h" /* Afs-based standard headers */ | ||
| 23 | #include "afs/afs_stats.h" /* statistics */ | ||
| 24 | #include "afs/afs_cbqueue.h" | ||
| 25 | #include "afs/nfsclient.h" | ||
| 26 | #include "afs/afs_osidnlc.h" | ||
| 27 | |||
| 28 | extern afs_rwlock_t afs_xcbhash; | ||
| 29 | |||
| 30 | /* Note that we don't set CDirty here, this is OK because the rename | ||
| 31 | * RPC is called synchronously. */ | ||
| 32 | |||
| 33 | int | ||
| 34 | afsrename(struct vcache *aodp, char *aname1, struct vcache *andp, | ||
| 35 | char *aname2, afs_ucred_tstruct usr_ucred *acred, struct vrequest *areq) | ||
| 36 | { | ||
| 37 | struct afs_conn *tc; | ||
| 38 | afs_int32 code = 0; | ||
| 39 | afs_int32 returnCode; | ||
| 40 | int oneDir, doLocally; | ||
| 41 | afs_size_t offset, len; | ||
| 42 | struct VenusFid unlinkFid, fileFid; | ||
| 43 | struct vcache *tvc; | ||
| 44 | struct dcache *tdc1, *tdc2; | ||
| 45 | struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus; | ||
| 46 | struct AFSVolSync tsync; | ||
| 47 | struct rx_connection *rxconn; | ||
| 48 | XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t opStartTime = { 0, 0}, opStopTime, elapsedTime; | ||
| 49 | AFS_STATCNT(afs_rename)((afs_cmstats.callInfo.C_afs_rename)++); | ||
| 50 | afs_Trace4(afs_iclSetp, CM_TRACE_RENAME, ICL_TYPE_POINTER, aodp,(((afs_iclSetp) && (afs_iclSetp->states & 2)) ? afs_icl_Event4(afs_iclSetp, (701087828L), (1<<24)+((2) <<18)+((4)<<12)+((2)<<6)+(4), (long)(aodp), (long)(aname1), (long)(andp), (long)(aname2)) : 0) | ||
| 51 | ICL_TYPE_STRING, aname1, ICL_TYPE_POINTER, andp,(((afs_iclSetp) && (afs_iclSetp->states & 2)) ? afs_icl_Event4(afs_iclSetp, (701087828L), (1<<24)+((2) <<18)+((4)<<12)+((2)<<6)+(4), (long)(aodp), (long)(aname1), (long)(andp), (long)(aname2)) : 0) | ||
| 52 | ICL_TYPE_STRING, aname2)(((afs_iclSetp) && (afs_iclSetp->states & 2)) ? afs_icl_Event4(afs_iclSetp, (701087828L), (1<<24)+((2) <<18)+((4)<<12)+((2)<<6)+(4), (long)(aodp), (long)(aname1), (long)(andp), (long)(aname2)) : 0); | ||
| 53 | |||
| 54 | if (strlen(aname1) > AFSNAMEMAX256 || strlen(aname2) > AFSNAMEMAX256) { | ||
| |||
| 55 | code = ENAMETOOLONG63; | ||
| 56 | goto done; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* verify the latest versions of the stat cache entries */ | ||
| 60 | tagain: | ||
| 61 | code = afs_VerifyVCache(aodp, areq)(((aodp)->f.states & 0x00000001) ? 0 : afs_VerifyVCache2 ((aodp),areq)); | ||
| 62 | if (code) | ||
| |||
| |||
| |||
| |||
| 63 | goto done; | ||
| 64 | code = afs_VerifyVCache(andp, areq)(((andp)->f.states & 0x00000001) ? 0 : afs_VerifyVCache2 ((andp),areq)); | ||
| 65 | if (code) | ||
| |||
| |||
| |||
| |||
| 66 | goto done; | ||
| 67 | |||
| 68 | /* lock in appropriate order, after some checks */ | ||
| 69 | if (aodp->f.fidusr_fid.Cell != andp->f.fidusr_fid.Cell | ||
| |||
| |||
| |||
| |||
| 70 | || aodp->f.fidusr_fid.Fid.Volume != andp->f.fidusr_fid.Fid.Volume) { | ||
| 71 | code = EXDEV18; | ||
| 72 | goto done; | ||
| 73 | } | ||
| 74 | oneDir = 0; | ||
| 75 | code = 0; | ||
| 76 | if (andp->f.fidusr_fid.Fid.Vnode == aodp->f.fidusr_fid.Fid.Vnode) { | ||
| |||
| |||
| |||
| |||
| 77 | if (!strcmp(aname1, aname2)) { | ||
| 78 | /* Same directory and same name; this is a noop and just return success | ||
| 79 | * to save cycles and follow posix standards */ | ||
| 80 | |||
| 81 | code = 0; | ||
| 82 | goto done; | ||
| 83 | } | ||
| 84 | |||
| 85 | if (AFS_IS_DISCONNECTED(afs_is_disconnected) && !AFS_IS_DISCON_RW(afs_is_discon_rw)) { | ||
| 86 | code = ENETDOWN50; | ||
| 87 | goto done; | ||
| 88 | } | ||
| 89 | |||
| 90 | ObtainWriteLock(&andp->lock, 147)do { ; if (!(&andp->lock)->excl_locked && ! (&andp->lock)->readers_reading) (&andp->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&andp->lock , 2); (&andp->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&andp->lock)->src_indicator = 147; } while (0); | ||
| 91 | tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0); | ||
| 92 | if (!tdc1) { | ||
| 93 | code = ENOENT2; | ||
| 94 | } else { | ||
| 95 | ObtainWriteLock(&tdc1->lock, 643)do { ; if (!(&tdc1->lock)->excl_locked && ! (&tdc1->lock)->readers_reading) (&tdc1->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc1->lock , 2); (&tdc1->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc1->lock)->src_indicator = 643; } while (0); | ||
| 96 | } | ||
| 97 | tdc2 = tdc1; | ||
| 98 | oneDir = 1; /* only one dude locked */ | ||
| 99 | } else if ((andp->f.states & CRO0x00000004) || (aodp->f.states & CRO0x00000004)) { | ||
| |||
| |||
| |||
| |||
| 100 | code = EROFS30; | ||
| 101 | goto done; | ||
| 102 | } else if (andp->f.fidusr_fid.Fid.Vnode < aodp->f.fidusr_fid.Fid.Vnode) { | ||
| |||
| |||
| |||
| |||
| 103 | ObtainWriteLock(&andp->lock, 148)do { ; if (!(&andp->lock)->excl_locked && ! (&andp->lock)->readers_reading) (&andp->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&andp->lock , 2); (&andp->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&andp->lock)->src_indicator = 148; } while (0); /* lock smaller one first */ | ||
| 104 | ObtainWriteLock(&aodp->lock, 149)do { ; if (!(&aodp->lock)->excl_locked && ! (&aodp->lock)->readers_reading) (&aodp->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&aodp->lock , 2); (&aodp->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&aodp->lock)->src_indicator = 149; } while (0); | ||
| 105 | tdc2 = afs_FindDCache(andp, (afs_size_t) 0); | ||
| 106 | if (tdc2) | ||
| 107 | ObtainWriteLock(&tdc2->lock, 644)do { ; if (!(&tdc2->lock)->excl_locked && ! (&tdc2->lock)->readers_reading) (&tdc2->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc2->lock , 2); (&tdc2->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc2->lock)->src_indicator = 644; } while (0); | ||
| 108 | tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0); | ||
| 109 | if (tdc1) | ||
| 110 | ObtainWriteLock(&tdc1->lock, 645)do { ; if (!(&tdc1->lock)->excl_locked && ! (&tdc1->lock)->readers_reading) (&tdc1->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc1->lock , 2); (&tdc1->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc1->lock)->src_indicator = 645; } while (0); | ||
| 111 | else | ||
| 112 | code = ENOENT2; | ||
| 113 | } else { | ||
| 114 | ObtainWriteLock(&aodp->lock, 150)do { ; if (!(&aodp->lock)->excl_locked && ! (&aodp->lock)->readers_reading) (&aodp->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&aodp->lock , 2); (&aodp->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&aodp->lock)->src_indicator = 150; } while (0); /* lock smaller one first */ | ||
| 115 | ObtainWriteLock(&andp->lock, 557)do { ; if (!(&andp->lock)->excl_locked && ! (&andp->lock)->readers_reading) (&andp->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&andp->lock , 2); (&andp->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&andp->lock)->src_indicator = 557; } while (0); | ||
| 116 | tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0); | ||
| 117 | if (tdc1) | ||
| |||
| |||
| |||
| |||
| 118 | ObtainWriteLock(&tdc1->lock, 646)do { ; if (!(&tdc1->lock)->excl_locked && ! (&tdc1->lock)->readers_reading) (&tdc1->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc1->lock , 2); (&tdc1->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc1->lock)->src_indicator = 646; } while (0); | ||
| 119 | else | ||
| 120 | code = ENOENT2; | ||
| 121 | tdc2 = afs_FindDCache(andp, (afs_size_t) 0); | ||
| 122 | if (tdc2) | ||
| |||
| |||
| |||
| |||
| 123 | ObtainWriteLock(&tdc2->lock, 647)do { ; if (!(&tdc2->lock)->excl_locked && ! (&tdc2->lock)->readers_reading) (&tdc2->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc2->lock , 2); (&tdc2->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc2->lock)->src_indicator = 647; } while (0); | ||
| 124 | } | ||
| 125 | |||
| 126 | osi_dnlc_remove(aodp, aname1, 0); | ||
| 127 | osi_dnlc_remove(andp, aname2, 0); | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Make sure that the data in the cache is current. We may have | ||
| 131 | * received a callback while we were waiting for the write lock. | ||
| 132 | */ | ||
| 133 | if (tdc1) { | ||
| |||
| |||
| |||
| |||
| 134 | if (!(aodp->f.states & CStatd0x00000001) | ||
| |||
| |||
| |||
| |||
| 135 | || !hsame(aodp->f.m.DataVersion, tdc1->f.versionNo)((aodp->f.m.DataVersion).low == (tdc1->f.versionNo).low && (aodp->f.m.DataVersion).high == (tdc1->f.versionNo ).high)) { | ||
| 136 | |||
| 137 | ReleaseWriteLock(&aodp->lock)do { ; (&aodp->lock)->excl_locked &= ~2; if ((& aodp->lock)->wait_states) Afs_Lock_ReleaseR(&aodp-> lock); (&aodp->lock)->pid_writer=0; } while (0); | ||
| 138 | if (!oneDir) { | ||
| |||
| |||
| |||
| 139 | if (tdc2) { | ||
| |||
| |||
| |||
| 140 | ReleaseWriteLock(&tdc2->lock)do { ; (&tdc2->lock)->excl_locked &= ~2; if ((& tdc2->lock)->wait_states) Afs_Lock_ReleaseR(&tdc2-> lock); (&tdc2->lock)->pid_writer=0; } while (0); | ||
| 141 | afs_PutDCache(tdc2); | ||
| 142 | } | ||
| 143 | ReleaseWriteLock(&andp->lock)do { ; (&andp->lock)->excl_locked &= ~2; if ((& andp->lock)->wait_states) Afs_Lock_ReleaseR(&andp-> lock); (&andp->lock)->pid_writer=0; } while (0); | ||
| 144 | } | ||
| 145 | ReleaseWriteLock(&tdc1->lock)do { ; (&tdc1->lock)->excl_locked &= ~2; if ((& tdc1->lock)->wait_states) Afs_Lock_ReleaseR(&tdc1-> lock); (&tdc1->lock)->pid_writer=0; } while (0); | ||
| 146 | afs_PutDCache(tdc1); | ||
| 147 | goto tagain; | ||
| |||
| |||
| |||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | if (code == 0) | ||
| |||
| 152 | code = afs_dir_Lookup(tdc1, aname1, &fileFid.Fid); | ||
| 153 | if (code) { | ||
| |||
| 154 | if (tdc1) { | ||
| 155 | ReleaseWriteLock(&tdc1->lock)do { ; (&tdc1->lock)->excl_locked &= ~2; if ((& tdc1->lock)->wait_states) Afs_Lock_ReleaseR(&tdc1-> lock); (&tdc1->lock)->pid_writer=0; } while (0); | ||
| 156 | afs_PutDCache(tdc1); | ||
| 157 | } | ||
| 158 | ReleaseWriteLock(&aodp->lock)do { ; (&aodp->lock)->excl_locked &= ~2; if ((& aodp->lock)->wait_states) Afs_Lock_ReleaseR(&aodp-> lock); (&aodp->lock)->pid_writer=0; } while (0); | ||
| 159 | if (!oneDir) { | ||
| 160 | if (tdc2) { | ||
| 161 | ReleaseWriteLock(&tdc2->lock)do { ; (&tdc2->lock)->excl_locked &= ~2; if ((& tdc2->lock)->wait_states) Afs_Lock_ReleaseR(&tdc2-> lock); (&tdc2->lock)->pid_writer=0; } while (0); | ||
| 162 | afs_PutDCache(tdc2); | ||
| 163 | } | ||
| 164 | ReleaseWriteLock(&andp->lock)do { ; (&andp->lock)->excl_locked &= ~2; if ((& andp->lock)->wait_states) Afs_Lock_ReleaseR(&andp-> lock); (&andp->lock)->pid_writer=0; } while (0); | ||
| 165 | } | ||
| 166 | goto done; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (!AFS_IS_DISCON_RW(afs_is_discon_rw)) { | ||
| |||
| 170 | /* Connected. */ | ||
| 171 | do { | ||
| 172 | tc = afs_Conn(&aodp->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn); | ||
| 173 | if (tc) { | ||
| 174 | XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[8]); osi_GetTime (&opStartTime);; | ||
| 175 | RX_AFS_GUNLOCK()do { do { if (!(pthread_self() == afs_global_owner)) { osi_Panic ("afs global lock not held"); } } while(0); memset(&afs_global_owner , 0, sizeof(pthread_t)); do{if (!(pthread_mutex_unlock(&afs_global_lock ) == 0)) AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_rename.c" , 175);}while(0); } while(0); | ||
| 176 | code = | ||
| 177 | RXAFS_Rename(rxconn, | ||
| 178 | (struct AFSFid *)&aodp->f.fidusr_fid.Fid, | ||
| 179 | aname1, | ||
| 180 | (struct AFSFid *)&andp->f.fidusr_fid.Fid, | ||
| 181 | aname2, | ||
| 182 | &OutOldDirStatus, | ||
| 183 | &OutNewDirStatus, | ||
| 184 | &tsync); | ||
| 185 | RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0)) AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_rename.c" , 185);}while(0); afs_global_owner = pthread_self(); } while( 0); | ||
| 186 | XSTATS_END_TIMEosi_GetTime(&opStopTime); (opP->numOps)++; if (!code) { (opP->numSuccesses)++; { if (opStopTime.tv_usec < opStartTime .tv_usec) { opStopTime.tv_usec += 1000000; opStopTime.tv_sec -= 1; } elapsedTime.tv_sec = opStopTime.tv_sec - opStartTime.tv_sec ; elapsedTime.tv_usec = opStopTime.tv_usec - opStartTime.tv_usec ; }; { (opP->sumTime).tv_sec += elapsedTime.tv_sec; (opP-> sumTime).tv_usec += elapsedTime.tv_usec; if ((opP->sumTime ).tv_usec > 1000000) { (opP->sumTime).tv_usec -= 1000000 ; (opP->sumTime).tv_sec++; } }; { if(elapsedTime.tv_sec > 0 ) { (opP->sqrTime).tv_sec += elapsedTime.tv_sec * elapsedTime .tv_sec + 2 * elapsedTime.tv_sec * elapsedTime.tv_usec /1000000 ; (opP->sqrTime).tv_usec += (2 * elapsedTime.tv_sec * elapsedTime .tv_usec) % 1000000 + (elapsedTime.tv_usec / 1000)*(elapsedTime .tv_usec / 1000) + 2 * (elapsedTime.tv_usec / 1000) * (elapsedTime .tv_usec % 1000) / 1000 + (((elapsedTime.tv_usec % 1000) > 707) ? 1 : 0); } else { (opP->sqrTime).tv_usec += (elapsedTime .tv_usec / 1000)*(elapsedTime.tv_usec / 1000) + 2 * (elapsedTime .tv_usec / 1000) * (elapsedTime.tv_usec % 1000) / 1000 + (((elapsedTime .tv_usec % 1000) > 707) ? 1 : 0); } if ((opP->sqrTime). tv_usec > 1000000) { (opP->sqrTime).tv_usec -= 1000000; (opP->sqrTime).tv_sec++; } }; if (((elapsedTime.tv_sec < (opP->minTime).tv_sec) ? 1 : (elapsedTime.tv_sec > (opP ->minTime).tv_sec) ? 0 : (elapsedTime.tv_usec < (opP-> minTime).tv_usec) ? 1 : 0)) { { (opP->minTime).tv_sec = elapsedTime .tv_sec; (opP->minTime).tv_usec = elapsedTime.tv_usec; }; } if (((elapsedTime.tv_sec > (opP->maxTime).tv_sec) ? 1 : (elapsedTime.tv_sec < (opP->maxTime).tv_sec) ? 0 : (elapsedTime .tv_usec > (opP->maxTime).tv_usec) ? 1 : 0)) { { (opP-> maxTime).tv_sec = elapsedTime.tv_sec; (opP->maxTime).tv_usec = elapsedTime.tv_usec; }; } }; | ||
| 187 | } else | ||
| 188 | code = -1; | ||
| 189 | |||
| 190 | } while (afs_Analyze | ||
| 191 | (tc, rxconn, code, &andp->f.fidusr_fid, areq, AFS_STATS_FS_RPCIDX_RENAME8, | ||
| 192 | SHARED_LOCK4, NULL((void *)0))); | ||
| 193 | |||
| 194 | } else { | ||
| 195 | /* Disconnected. */ | ||
| 196 | |||
| 197 | /* Seek moved file vcache. */ | ||
| 198 | fileFid.Cell = aodp->f.fidusr_fid.Cell; | ||
| 199 | fileFid.Fid.Volume = aodp->f.fidusr_fid.Fid.Volume; | ||
| 200 | ObtainSharedLock(&afs_xvcache, 754)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache ) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache , 4); (&afs_xvcache)->pid_writer = (get_user_struct()-> u_procp->p_pid ); (&afs_xvcache)->src_indicator = 754 ; } while (0); | ||
| 201 | tvc = afs_FindVCache(&fileFid, 0 , 1); | ||
| 202 | ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if ((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(& afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0 ); | ||
| 203 | |||
| 204 | if (tvc) { | ||
| |||
| 205 | /* XXX - We're locking this vcache whilst holding dcaches. Ooops */ | ||
| 206 | ObtainWriteLock(&tvc->lock, 750)do { ; if (!(&tvc->lock)->excl_locked && !( &tvc->lock)->readers_reading) (&tvc->lock) -> excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2); (&tvc->lock)->pid_writer = (get_user_struct()-> u_procp->p_pid ); (&tvc->lock)->src_indicator = 750 ; } while (0); | ||
| 207 | if (!(tvc->f.ddirty_flags & (VDisconRename0x00010000|VDisconCreate0x00004000))) { | ||
| |||
| 208 | /* If the vnode was created locally, then we don't care | ||
| 209 | * about recording the rename - we'll do it automatically | ||
| 210 | * on replay. If we've already renamed, we've already stored | ||
| 211 | * the required information about where we came from. | ||
| 212 | */ | ||
| 213 | |||
| 214 | if (!aodp->f.shadow.vnodeusr_vnode) { | ||
| 215 | /* Make shadow copy of parent dir only. */ | ||
| 216 | afs_MakeShadowDir(aodp, tdc1); | ||
| 217 | } | ||
| 218 | |||
| 219 | /* Save old parent dir fid so it will be searchable | ||
| 220 | * in the shadow dir. | ||
| 221 | */ | ||
| 222 | tvc->f.oldParent.vnodeusr_vnode = aodp->f.fidusr_fid.Fid.Vnode; | ||
| 223 | tvc->f.oldParent.unique = aodp->f.fidusr_fid.Fid.Unique; | ||
| 224 | |||
| 225 | afs_DisconAddDirty(tvc, | ||
| 226 | VDisconRename0x00010000 | ||
| 227 | | (oneDir ? VDisconRenameSameDir0x00020000:0), | ||
| 228 | 1); | ||
| 229 | } | ||
| 230 | |||
| 231 | ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((& tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc-> lock); (&tvc->lock)->pid_writer=0; } while (0); | ||
| 232 | afs_PutVCache(tvc); | ||
| 233 | } else { | ||
| 234 | code = ENOENT2; | ||
| 235 | } /* if (tvc) */ | ||
| 236 | } /* if !(AFS_IS_DISCON_RW)*/ | ||
| 237 | returnCode = code; /* remember for later */ | ||
| 238 | |||
| 239 | /* Now we try to do things locally. This is really loathsome code. */ | ||
| 240 | unlinkFid.Fid.Vnode = 0; | ||
| 241 | if (code == 0) { | ||
| |||
| 242 | /* In any event, we don't really care if the data (tdc2) is not | ||
| 243 | * in the cache; if it isn't, we won't do the update locally. */ | ||
| 244 | /* see if version numbers increased properly */ | ||
| 245 | doLocally = 1; | ||
| 246 | if (!AFS_IS_DISCON_RW(afs_is_discon_rw)) { | ||
| |||
| 247 | if (oneDir) { | ||
| 248 | /* number increases by 1 for whole rename operation */ | ||
| 249 | if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1)) { | ||
| 250 | doLocally = 0; | ||
| 251 | } | ||
| 252 | } else { | ||
| 253 | /* two separate dirs, each increasing by 1 */ | ||
| 254 | if (!afs_LocalHero(aodp, tdc1, &OutOldDirStatus, 1)) | ||
| 255 | doLocally = 0; | ||
| 256 | if (!afs_LocalHero(andp, tdc2, &OutNewDirStatus, 1)) | ||
| 257 | doLocally = 0; | ||
| 258 | if (!doLocally) { | ||
| 259 | if (tdc1) { | ||
| 260 | ZapDCE(tdc1)do { (tdc1)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc1 )->index] = 0; (tdc1)->dflags |= 0x02; } while(0); | ||
| 261 | DZap(tdc1); | ||
| 262 | } | ||
| 263 | if (tdc2) { | ||
| 264 | ZapDCE(tdc2)do { (tdc2)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc2 )->index] = 0; (tdc2)->dflags |= 0x02; } while(0); | ||
| 265 | DZap(tdc2); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } /* if (!AFS_IS_DISCON_RW) */ | ||
| 270 | |||
| 271 | /* now really do the work */ | ||
| 272 | if (doLocally) { | ||
| |||
| 273 | /* first lookup the fid of the dude we're moving */ | ||
| 274 | code = afs_dir_Lookup(tdc1, aname1, &fileFid.Fid); | ||
| 275 | if (code == 0) { | ||
| |||
| 276 | /* delete the source */ | ||
| 277 | code = afs_dir_Delete(tdc1, aname1); | ||
| 278 | } | ||
| 279 | /* first see if target is there */ | ||
| 280 | if (code == 0 | ||
| |||
| 281 | && afs_dir_Lookup(tdc2, aname2, | ||
| 282 | &unlinkFid.Fid) == 0) { | ||
| 283 | /* target already exists, and will be unlinked by server */ | ||
| 284 | code = afs_dir_Delete(tdc2, aname2); | ||
| 285 | } | ||
| 286 | if (code == 0) { | ||
| |||
| 287 | ObtainWriteLock(&afs_xdcache, 292)do { ; if (!(&afs_xdcache)->excl_locked && !(& afs_xdcache)->readers_reading) (&afs_xdcache) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_xdcache, 2); (&afs_xdcache )->pid_writer = (get_user_struct()->u_procp->p_pid ) ; (&afs_xdcache)->src_indicator = 292; } while (0); | ||
| 288 | code = afs_dir_Create(tdc2, aname2, &fileFid.Fid); | ||
| 289 | ReleaseWriteLock(&afs_xdcache)do { ; (&afs_xdcache)->excl_locked &= ~2; if ((& afs_xdcache)->wait_states) Afs_Lock_ReleaseR(&afs_xdcache ); (&afs_xdcache)->pid_writer=0; } while (0); | ||
| 290 | } | ||
| 291 | if (code != 0) { | ||
| |||
| 292 | ZapDCE(tdc1)do { (tdc1)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc1 )->index] = 0; (tdc1)->dflags |= 0x02; } while(0); | ||
| 293 | DZap(tdc1); | ||
| 294 | if (!oneDir) { | ||
| 295 | ZapDCE(tdc2)do { (tdc2)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc2 )->index] = 0; (tdc2)->dflags |= 0x02; } while(0); | ||
| 296 | DZap(tdc2); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | /* update dir link counts */ | ||
| 303 | if (AFS_IS_DISCON_RW(afs_is_discon_rw)) { | ||
| |||
| 304 | if (!oneDir) { | ||
| 305 | aodp->f.m.LinkCount--; | ||
| 306 | andp->f.m.LinkCount++; | ||
| 307 | } | ||
| 308 | /* If we're in the same directory, link count doesn't change */ | ||
| 309 | } else { | ||
| 310 | aodp->f.m.LinkCount = OutOldDirStatus.LinkCount; | ||
| |||
| 311 | if (!oneDir) | ||
| 312 | andp->f.m.LinkCount = OutNewDirStatus.LinkCount; | ||
| 313 | } | ||
| 314 | |||
| 315 | } else { /* operation failed (code != 0) */ | ||
| 316 | if (code < 0) { | ||
| 317 | /* if failed, server might have done something anyway, and | ||
| 318 | * assume that we know about it */ | ||
| 319 | ObtainWriteLock(&afs_xcbhash, 498)do { ; if (!(&afs_xcbhash)->excl_locked && !(& afs_xcbhash)->readers_reading) (&afs_xcbhash) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_xcbhash, 2); (&afs_xcbhash )->pid_writer = (get_user_struct()->u_procp->p_pid ) ; (&afs_xcbhash)->src_indicator = 498; } while (0); | ||
| 320 | afs_DequeueCallback(aodp); | ||
| 321 | afs_DequeueCallback(andp); | ||
| 322 | andp->f.states &= ~CStatd0x00000001; | ||
| 323 | aodp->f.states &= ~CStatd0x00000001; | ||
| 324 | ReleaseWriteLock(&afs_xcbhash)do { ; (&afs_xcbhash)->excl_locked &= ~2; if ((& afs_xcbhash)->wait_states) Afs_Lock_ReleaseR(&afs_xcbhash ); (&afs_xcbhash)->pid_writer=0; } while (0); | ||
| 325 | osi_dnlc_purgedp(andp); | ||
| 326 | osi_dnlc_purgedp(aodp); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | /* release locks */ | ||
| 331 | if (tdc1) { | ||
| 332 | ReleaseWriteLock(&tdc1->lock)do { ; (&tdc1->lock)->excl_locked &= ~2; if ((& tdc1->lock)->wait_states) Afs_Lock_ReleaseR(&tdc1-> lock); (&tdc1->lock)->pid_writer=0; } while (0); | ||
| 333 | afs_PutDCache(tdc1); | ||
| 334 | } | ||
| 335 | |||
| 336 | if ((!oneDir) && tdc2) { | ||
| 337 | ReleaseWriteLock(&tdc2->lock)do { ; (&tdc2->lock)->excl_locked &= ~2; if ((& tdc2->lock)->wait_states) Afs_Lock_ReleaseR(&tdc2-> lock); (&tdc2->lock)->pid_writer=0; } while (0); | ||
| 338 | afs_PutDCache(tdc2); | ||
| 339 | } | ||
| 340 | |||
| 341 | ReleaseWriteLock(&aodp->lock)do { ; (&aodp->lock)->excl_locked &= ~2; if ((& aodp->lock)->wait_states) Afs_Lock_ReleaseR(&aodp-> lock); (&aodp->lock)->pid_writer=0; } while (0); | ||
| 342 | |||
| 343 | if (!oneDir) { | ||
| 344 | ReleaseWriteLock(&andp->lock)do { ; (&andp->lock)->excl_locked &= ~2; if ((& andp->lock)->wait_states) Afs_Lock_ReleaseR(&andp-> lock); (&andp->lock)->pid_writer=0; } while (0); | ||
| 345 | } | ||
| 346 | |||
| 347 | if (returnCode) { | ||
| 348 | code = returnCode; | ||
| 349 | goto done; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* now, some more details. if unlinkFid.Fid.Vnode then we should decrement | ||
| 353 | * the link count on this file. Note that if fileFid is a dir, then we don't | ||
| 354 | * have to invalidate its ".." entry, since its DataVersion # should have | ||
| 355 | * changed. However, interface is not good enough to tell us the | ||
| 356 | * *file*'s new DataVersion, so we're stuck. Our hack: delete mark | ||
| 357 | * the data as having an "unknown" version (effectively discarding the ".." | ||
| 358 | * entry */ | ||
| 359 | if (unlinkFid.Fid.Vnode) { | ||
| 360 | |||
| 361 | unlinkFid.Fid.Volume = aodp->f.fidusr_fid.Fid.Volume; | ||
| 362 | unlinkFid.Cell = aodp->f.fidusr_fid.Cell; | ||
| 363 | tvc = NULL((void *)0); | ||
| 364 | if (!unlinkFid.Fid.Unique) { | ||
| 365 | tvc = afs_LookupVCache(&unlinkFid, areq, NULL((void *)0), aodp, aname1); | ||
| 366 | } | ||
| 367 | if (!tvc) /* lookup failed or wasn't called */ | ||
| 368 | tvc = afs_GetVCache(&unlinkFid, areq, NULL((void *)0), NULL((void *)0)); | ||
| 369 | |||
| 370 | if (tvc) { | ||
| 371 | #ifdef AFS_BOZONLOCK_ENV | ||
| 372 | afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */ | ||
| 373 | #endif | ||
| 374 | ObtainWriteLock(&tvc->lock, 151)do { ; if (!(&tvc->lock)->excl_locked && !( &tvc->lock)->readers_reading) (&tvc->lock) -> excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2); (&tvc->lock)->pid_writer = (get_user_struct()-> u_procp->p_pid ); (&tvc->lock)->src_indicator = 151 ; } while (0); | ||
| 375 | tvc->f.m.LinkCount--; | ||
| 376 | tvc->f.states &= ~CUnique0x00001000; /* For the dfs xlator */ | ||
| 377 | if (tvc->f.m.LinkCount == 0 && !osi_Active(tvc)) { | ||
| 378 | /* if this was last guy (probably) discard from cache. | ||
| 379 | * We have to be careful to not get rid of the stat | ||
| 380 | * information, since otherwise operations will start | ||
| 381 | * failing even if the file was still open (or | ||
| 382 | * otherwise active), and the server no longer has the | ||
| 383 | * info. If the file still has valid links, we'll get | ||
| 384 | * a break-callback msg from the server, so it doesn't | ||
| 385 | * matter that we don't discard the status info */ | ||
| 386 | if (!AFS_NFSXLATORREQ(acred)(((acred)->cr_rgid) == 0xaaaa)) | ||
| 387 | afs_TryToSmush(tvc, acred, 0); | ||
| 388 | } | ||
| 389 | ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((& tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc-> lock); (&tvc->lock)->pid_writer=0; } while (0); | ||
| 390 | #ifdef AFS_BOZONLOCK_ENV | ||
| 391 | afs_BozonUnlock(&tvc->pvnLock, tvc); | ||
| 392 | #endif | ||
| 393 | afs_PutVCache(tvc); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | /* now handle ".." invalidation */ | ||
| 398 | if (!oneDir) { | ||
| 399 | fileFid.Fid.Volume = aodp->f.fidusr_fid.Fid.Volume; | ||
| 400 | fileFid.Cell = aodp->f.fidusr_fid.Cell; | ||
| 401 | if (!fileFid.Fid.Unique) | ||
| 402 | tvc = afs_LookupVCache(&fileFid, areq, NULL((void *)0), andp, aname2); | ||
| 403 | else | ||
| 404 | tvc = afs_GetVCache(&fileFid, areq, NULL((void *)0), (struct vcache *)0); | ||
| 405 | if (tvc && (vType(tvc)(tvc)->v.v_type == VDIR0040000)) { | ||
| 406 | ObtainWriteLock(&tvc->lock, 152)do { ; if (!(&tvc->lock)->excl_locked && !( &tvc->lock)->readers_reading) (&tvc->lock) -> excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2); (&tvc->lock)->pid_writer = (get_user_struct()-> u_procp->p_pid ); (&tvc->lock)->src_indicator = 152 ; } while (0); | ||
| 407 | tdc1 = afs_FindDCache(tvc, (afs_size_t) 0); | ||
| 408 | if (tdc1) { | ||
| 409 | if (AFS_IS_DISCON_RW(afs_is_discon_rw)) { | ||
| 410 | /* If disconnected, we need to fix (not discard) the "..".*/ | ||
| 411 | afs_dir_ChangeFid(tdc1, | ||
| 412 | "..", | ||
| 413 | &aodp->f.fidusr_fid.Fid.Vnode, | ||
| 414 | &andp->f.fidusr_fid.Fid.Vnode); | ||
| 415 | } else { | ||
| 416 | ObtainWriteLock(&tdc1->lock, 648)do { ; if (!(&tdc1->lock)->excl_locked && ! (&tdc1->lock)->readers_reading) (&tdc1->lock ) -> excl_locked = 2; else Afs_Lock_Obtain(&tdc1->lock , 2); (&tdc1->lock)->pid_writer = (get_user_struct( )->u_procp->p_pid ); (&tdc1->lock)->src_indicator = 648; } while (0); | ||
| 417 | ZapDCE(tdc1)do { (tdc1)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc1 )->index] = 0; (tdc1)->dflags |= 0x02; } while(0); /* mark as unknown */ | ||
| 418 | DZap(tdc1); | ||
| 419 | ReleaseWriteLock(&tdc1->lock)do { ; (&tdc1->lock)->excl_locked &= ~2; if ((& tdc1->lock)->wait_states) Afs_Lock_ReleaseR(&tdc1-> lock); (&tdc1->lock)->pid_writer=0; } while (0); | ||
| 420 | afs_PutDCache(tdc1); /* put it back */ | ||
| 421 | } | ||
| 422 | } | ||
| 423 | osi_dnlc_remove(tvc, "..", 0); | ||
| 424 | ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((& tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc-> lock); (&tvc->lock)->pid_writer=0; } while (0); | ||
| 425 | afs_PutVCache(tvc); | ||
| 426 | } else if (AFS_IS_DISCON_RW(afs_is_discon_rw) && tvc && (vType(tvc)(tvc)->v.v_type == VREG0100000)) { | ||
| 427 | /* XXX - Should tvc not get locked here? */ | ||
| 428 | tvc->f.parent.vnodeusr_vnode = andp->f.fidusr_fid.Fid.Vnode; | ||
| 429 | tvc->f.parent.unique = andp->f.fidusr_fid.Fid.Unique; | ||
| 430 | } else if (tvc) { | ||
| 431 | /* True we shouldn't come here since tvc SHOULD be a dir, but we | ||
| 432 | * 'syntactically' need to unless we change the 'if' above... | ||
| 433 | */ | ||
| 434 | afs_PutVCache(tvc); | ||
| 435 | } | ||
| 436 | } | ||
| 437 | code = returnCode; | ||
| 438 | done: | ||
| 439 | return code; | ||
| 440 | } | ||
| 441 | |||
| 442 | int | ||
| 443 | #if defined(AFS_SGI_ENV) | ||
| 444 | afs_rename(OSI_VC_DECL(aodp)struct vcache *aodp, char *aname1, struct vcache *andp, char *aname2, struct pathname *npnp, afs_ucred_tstruct usr_ucred *acred) | ||
| 445 | #else | ||
| 446 | afs_rename(OSI_VC_DECL(aodp)struct vcache *aodp, char *aname1, struct vcache *andp, char *aname2, afs_ucred_tstruct usr_ucred *acred) | ||
| 447 | #endif | ||
| 448 | { | ||
| 449 | afs_int32 code; | ||
| 450 | struct afs_fakestat_state ofakestate; | ||
| 451 | struct afs_fakestat_state nfakestate; | ||
| 452 | struct vrequest treq; | ||
| 453 | OSI_VC_CONVERT(aodp); | ||
| 454 | |||
| 455 | code = afs_InitReq(&treq, acred); | ||
| 456 | if (code) | ||
| 457 | return code; | ||
| 458 | afs_InitFakeStat(&ofakestate); | ||
| 459 | afs_InitFakeStat(&nfakestate); | ||
| 460 | |||
| 461 | AFS_DISCON_LOCK()do { ; if (!((&afs_discon_lock)->excl_locked & 2)) ((&afs_discon_lock)->readers_reading)++; else Afs_Lock_Obtain (&afs_discon_lock, 1); (&afs_discon_lock)->pid_last_reader = (get_user_struct()->u_procp->p_pid ); } while (0); | ||
| 462 | |||
| 463 | code = afs_EvalFakeStat(&aodp, &ofakestate, &treq); | ||
| 464 | if (code) | ||
| 465 | goto done; | ||
| 466 | code = afs_EvalFakeStat(&andp, &nfakestate, &treq); | ||
| 467 | if (code) | ||
| 468 | goto done; | ||
| 469 | code = afsrename(aodp, aname1, andp, aname2, acred, &treq); | ||
| 470 | done: | ||
| 471 | afs_PutFakeStat(&ofakestate); | ||
| 472 | afs_PutFakeStat(&nfakestate); | ||
| 473 | |||
| 474 | AFS_DISCON_UNLOCK()do { ; if (!(--((&afs_discon_lock)->readers_reading)) && (&afs_discon_lock)->wait_states) Afs_Lock_ReleaseW(& afs_discon_lock) ; if ( (&afs_discon_lock)->pid_last_reader == (get_user_struct()->u_procp->p_pid ) ) (&afs_discon_lock )->pid_last_reader =0; } while (0); | ||
| 475 | |||
| 476 | code = afs_CheckCode(code, &treq, 25); | ||
| 477 | return code; | ||
| 478 | } |