From: Asanka Herath Date: Mon, 9 Jan 2006 04:49:17 +0000 (+0000) Subject: STABLE14-windows-byte-range-locking-20060108 X-Git-Tag: openafs-stable-1_4_1-rc4~11 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=8f65c99214a86f474eb50559673bf05662b9dfc2;p=packages%2Fo%2Fopenafs.git STABLE14-windows-byte-range-locking-20060108 When SMB sessions are prematurely terminated as part of the tear down of the virtual circuit we must clean up any remaining file handles, tree connections, and user sessions. (cherry picked from commit 78c40badbd8c65d82f6c384fdff8056c03100b67) --- diff --git a/src/WINNT/afsd/cm_scache.h b/src/WINNT/afsd/cm_scache.h index 80e4e0914..48a8778ec 100644 --- a/src/WINNT/afsd/cm_scache.h +++ b/src/WINNT/afsd/cm_scache.h @@ -75,7 +75,10 @@ typedef struct cm_file_lock { #define CM_FILELOCK_FLAG_WAITLOCK 0x04 #define CM_FILELOCK_FLAG_WAITUNLOCK 0x0C -/* the following is only to be used for locks on non-RO volumes */ +/* the following is used to indicate that there are no server side + locks associated with this lock. This is true for locks obtained + against files in RO volumes as well as files residing on servers + that disable client side byte range locking. */ #define CM_FILELOCK_FLAG_CLIENTONLY 0x10 #define CM_FLSHARE_OFFSET_HIGH 0x01000000 diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index cd6580379..add22462e 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -3070,7 +3070,13 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp, /* unsafe */ #define CONTAINS_RANGE(r1,r2) (((r2).offset+(r2).length) <= ((r1).offset+(r1).length) && (r1).offset <= (r2).offset) -#define SERVERLOCKS_ENABLED(scp) (!((scp)->flags & CM_SCACHEFLAG_RO) && cm_enableServerLocks) +#if defined(VICED_CAPABILITY_USE_BYTE_RANGE_LOCKS) && !defined(LOCK_TESTING) +#define SCP_SUPPORTS_BRLOCKS(scp) ((scp)->cbServerp && ((scp)->cbServerp->capabilities & VICED_CAPABILITY_USE_BYTE_RANGE_LOCKS)) +#else +#define SCP_SUPPORTS_BRLOCKS(scp) (1) +#endif + +#define SERVERLOCKS_ENABLED(scp) (!((scp)->flags & CM_SCACHEFLAG_RO) && cm_enableServerLocks && SCP_SUPPORTS_BRLOCKS(scp)) static void cm_LockRangeSubtract(cm_range_t * pos, const cm_range_t * neg) { @@ -3597,8 +3603,11 @@ long cm_UnlockByKey(cm_scache_t * scp, struct rx_connection * callp; int n_unlocks = 0; - osi_Log3(afsd_logp, "cm_UnlockByKey scp 0x%x key 0x%x:%x", - (long) scp, (unsigned long)(key >> 32), (unsigned long)(key & 0xffffffff)); + osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%x key 0x%x:%x flags=0x%x", + (long) scp, + (unsigned long)(key >> 32), + (unsigned long)(key & 0xffffffff), + flags); lock_ObtainWrite(&cm_scacheLock); @@ -3610,7 +3619,9 @@ long cm_UnlockByKey(cm_scache_t * scp, #ifdef DEBUG osi_Log4(afsd_logp, " Checking lock[0x%x] range[%d,+%d] type[%d]", - fileLock, (unsigned long) fileLock->range.offset, (unsigned long) fileLock->range.length, + fileLock, + (unsigned long) fileLock->range.offset, + (unsigned long) fileLock->range.length, fileLock->lockType); osi_Log3(afsd_logp, " key[0x%x:%x] flags[0x%x]", (unsigned long)(fileLock->key >> 32), @@ -4143,7 +4154,7 @@ void cm_CheckLocks() /* Server locks must have been enabled for us to have received an active non-client-only lock. */ - //osi_assert(cm_enableServerLocks); + osi_assert(cm_enableServerLocks); scp = fileLock->scp; osi_assert(scp != NULL); @@ -4364,7 +4375,6 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead) if(IS_LOCK_WAITUNLOCK(oldFileLock)) { /* check if the conflicting locks have dissappeared already */ - for(q = scp->fileLocksH; q; q = osi_QNext(q)) { fileLock = (cm_file_lock_t *) @@ -4529,9 +4539,16 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead) cm_key_t cm_GenerateKey(unsigned int session_id, unsigned long process_id, unsigned int file_id) { - return (((cm_key_t) process_id) << 32) | - (((cm_key_t) session_id) << 16) | - (((cm_key_t) file_id)); +#ifdef DEBUG + osi_assert((process_id & 0xffffffff) == process_id); + osi_assert((session_id & 0xffff) == session_id); + osi_assert((file_id & 0xffff) == file_id); +#endif + + return + (((cm_key_t) (process_id & 0xffffffff)) << 32) | + (((cm_key_t) (session_id & 0xffff)) << 16) | + (((cm_key_t) (file_id & 0xffff))); } static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags) diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index bb2c2aadb..2d9de36aa 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -12,6 +12,8 @@ extern unsigned int cm_mountRootGen; +extern int cm_enableServerLocks; + /* parms for attribute setting call */ typedef struct cm_attr { int mask; @@ -150,7 +152,7 @@ extern long cm_Lock(cm_scache_t *scp, unsigned char sLockType, int allowWait, cm_user_t *userp, cm_req_t *reqp, cm_file_lock_t **lockpp); -#define CM_UNLOCK_BY_FID 1 +#define CM_UNLOCK_BY_FID 0x0001 extern long cm_UnlockByKey(cm_scache_t * scp, cm_key_t key, diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index cc0434ee3..a3b570824 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -918,6 +918,90 @@ void smb_HoldVC(smb_vc_t *vcp) lock_ReleaseWrite(&smb_rctLock); } +void smb_CleanupDeadVC(smb_vc_t *vcp) +{ + smb_fid_t *fidpIter; + smb_fid_t *fidpNext; + smb_fid_t *fidp; + unsigned short fid; + smb_tid_t *tidpIter; + smb_tid_t *tidpNext; + smb_tid_t *tidp; + unsigned short tid; + smb_user_t *userpIter; + smb_user_t *userpNext; + smb_user_t *userp; + unsigned short uid; + + osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp); + + lock_ObtainRead(&smb_rctLock); + for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) { + fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q); + + if (fidpIter->flags & SMB_FID_DELETE) + continue; + + fid = fidpIter->fid; + osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter); + lock_ReleaseRead(&smb_rctLock); + + fidp = smb_FindFID(vcp, fid, 0); + osi_assert(fidp); + smb_CloseFID(vcp, fidp, NULL, 0); + smb_ReleaseFID(fidp); + + lock_ObtainRead(&smb_rctLock); + } + + for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) { + tidpNext = tidpIter->nextp; + if (tidpIter->flags & SMB_TIDFLAG_DELETE) + continue; + + tid = tidpIter->tid; + osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter); + lock_ReleaseRead(&smb_rctLock); + + tidp = smb_FindTID(vcp, tid, 0); + osi_assert(tidp); + + lock_ObtainMutex(&tidp->mx); + tidp->flags |= SMB_TIDFLAG_DELETE; + lock_ReleaseMutex(&tidp->mx); + + smb_ReleaseTID(tidp); + + lock_ObtainRead(&smb_rctLock); + } + + for (userpIter = vcp->usersp; userpIter; userpIter = userpNext) { + userpNext = userpIter->nextp; + + if (userpIter->flags & SMB_USERFLAG_DELETE) + continue; + + uid = userpIter->userID; + osi_Log2(smb_logp, " Cleanup UID %d (userp=0x%x)", uid, userpIter); + lock_ReleaseRead(&smb_rctLock); + + userp = smb_FindUID(vcp, uid, 0); + osi_assert(userp); + + lock_ObtainMutex(&userp->mx); + userp->flags |= SMB_USERFLAG_DELETE; + lock_ReleaseMutex(&userp->mx); + + smb_ReleaseUID(userp); + + lock_ObtainRead(&smb_rctLock); + } + + lock_ReleaseRead(&smb_rctLock); + + osi_Log0(smb_logp, "Done cleaning up dead vcp"); +} + smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags) { smb_tid_t *tidp; @@ -1170,8 +1254,11 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) if (fid == fidp->fid) { if (newFid) { fid++; - if (fid == 0) + if (fid == 0) { + osi_Log1(smb_logp, + "New FID number wraps on vcp 0x%x", vcp); fid = 1; + } goto retry; } fidp->refCount++; @@ -1188,8 +1275,10 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName)); thrd_CloseHandle(event); fid++; - if (fid == 0) + if (fid == 0) { + osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp); fid = 1; + } goto retry; } @@ -1205,10 +1294,13 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) fidp->raw_write_event = event; if (newFid) { vcp->fidCounter = fid+1; - if (vcp->fidCounter == 0) + if (vcp->fidCounter == 0) { + osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x", + vcp); vcp->fidCounter = 1; } } + } lock_ReleaseWrite(&smb_rctLock); return fidp; @@ -1217,6 +1309,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) void smb_ReleaseFID(smb_fid_t *fidp) { cm_scache_t *scp; + cm_user_t *userp; smb_vc_t *vcp = NULL; smb_ioctl_t *ioctlp; @@ -1224,13 +1317,16 @@ void smb_ReleaseFID(smb_fid_t *fidp) return; scp = NULL; + userp = NULL; lock_ObtainWrite(&smb_rctLock); osi_assert(fidp->refCount-- > 0); if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) { vcp = fidp->vcp; - fidp->vcp = 0; + fidp->vcp = NULL; scp = fidp->scp; /* release after lock is released */ - fidp->scp = 0; + fidp->scp = NULL; + userp = fidp->userp; + fidp->userp = NULL; osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q); thrd_CloseHandle(fidp->raw_write_event); @@ -1256,6 +1352,9 @@ void smb_ReleaseFID(smb_fid_t *fidp) /* now release the scache structure */ if (scp) cm_ReleaseSCache(scp); + + if (userp) + cm_ReleaseUser(userp); } /* @@ -4587,6 +4686,9 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) /* save a pointer to the vnode */ fidp->scp = scp; + /* and the user */ + cm_HoldUser(userp); + fidp->userp = userp; if ((share & 0xf) == 0) fidp->flags |= SMB_FID_OPENREAD; @@ -5398,29 +5500,25 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp, *newPathp = strdup(pathp); } -long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) -{ - unsigned short fid; - smb_fid_t *fidp; - cm_user_t *userp; - afs_uint32 dosTime; +long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp, + afs_uint32 dosTime) { long code = 0; cm_req_t req; - cm_InitReq(&req); - - fid = smb_GetSMBParm(inp, 0); - dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16); - - osi_Log1(smb_logp, "SMB close fid %d", fid); + osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)", + fidp, fidp->fid, vcp); - fid = smb_ChainFID(fid, inp); - fidp = smb_FindFID(vcp, fid, 0); - if (!fidp) { + if (!userp) { + if (!fidp->userp) { + osi_Log0(smb_logp, " No user specified. Not closing fid"); return CM_ERROR_BADFD; } - userp = smb_GetUser(vcp, inp); + userp = fidp->userp; /* no hold required since fidp is held + throughout the function */ + } + + cm_InitReq(&req); lock_ObtainMutex(&fidp->mx); @@ -5452,12 +5550,12 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (!(fidp->flags & SMB_FID_IOCTL) && fidp->scp && fidp->scp->fileType == CM_SCACHETYPE_FILE) { cm_key_t key; - unsigned pid; cm_scache_t * scp; long tcode; - pid = ((smb_t *) inp)->pid; - key = cm_GenerateKey(vcp->vcID, pid, fid); + /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass + in zero. */ + key = cm_GenerateKey(vcp->vcID, 0, fidp->fid); scp = fidp->scp; cm_HoldSCache(scp); lock_ObtainMutex(&scp->mx); @@ -5468,7 +5566,8 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) | CM_SCACHESYNC_LOCK); if (tcode) { - osi_Log1(smb_logp, "smb CoreClose SyncOp failure code 0x%x", tcode); + osi_Log1(smb_logp, + "smb CoreClose SyncOp failure code 0x%x", tcode); goto post_syncopdone; } @@ -5494,9 +5593,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) smb_NotifyChange(FILE_ACTION_REMOVED, FILE_NOTIFY_CHANGE_DIR_NAME, dscp, fullPathp, NULL, TRUE); - } - else - { + } else { code = cm_Unlink(dscp, fullPathp, userp, &req); if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) smb_NotifyChange(FILE_ACTION_REMOVED, @@ -5510,9 +5607,38 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (fidp->flags & SMB_FID_NTOPEN) { cm_ReleaseSCache(fidp->NTopen_dscp); free(fidp->NTopen_pathp); + fidp->NTopen_pathp = NULL; } - if (fidp->NTopen_wholepathp) + if (fidp->NTopen_wholepathp) { free(fidp->NTopen_wholepathp); + fidp->NTopen_wholepathp = NULL; + } + + return code; +} + +long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +{ + unsigned short fid; + smb_fid_t *fidp; + cm_user_t *userp; + long code = 0; + afs_uint32 dosTime; + + fid = smb_GetSMBParm(inp, 0); + dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16); + + osi_Log1(smb_logp, "SMB ReceiveCoreClose fid %d", fid); + + fid = smb_ChainFID(fid, inp); + fidp = smb_FindFID(vcp, fid, 0); + if (!fidp) { + return CM_ERROR_BADFD; + } + + userp = smb_GetUser(vcp, inp); + + code = smb_CloseFID(vcp, fidp, userp, dosTime); smb_ReleaseFID(fidp); cm_ReleaseUser(userp); @@ -6630,6 +6756,9 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) /* save a pointer to the vnode */ fidp->scp = scp; + /* and the user */ + cm_HoldUser(userp); + fidp->userp = userp; /* always create it open for read/write */ fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE); @@ -7405,6 +7534,7 @@ void smb_Server(VOID *parmp) case NRC_SCLOSED: case NRC_SNUMOUT: + case NRC_SABORT: /* Client closed session */ dead_sessions[idx_session] = TRUE; if (vcp) @@ -7432,6 +7562,9 @@ void smb_Server(VOID *parmp) dead_vcp = vcp; vcp->flags |= SMB_VCFLAG_ALREADYDEAD; } + + smb_CleanupDeadVC(vcp); + if (vcp->justLoggedOut) { loggedOut = 1; loggedOutTime = vcp->logoffTime; diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 70a0f9796..89d668894 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -230,7 +230,7 @@ typedef struct smb_user { unsigned long refCount; /* ref count */ long flags; /* flags; locked by mx */ osi_mutex_t mx; - long userID; /* the session identifier */ + unsigned short userID; /* the session identifier */ struct smb_vc *vcp; /* back ptr to virtual circuit */ struct smb_username *unp; /* user name struct */ } smb_user_t; @@ -315,6 +315,10 @@ typedef struct smb_fid { unsigned short fid; /* the file ID */ struct smb_vc *vcp; /* back ptr */ struct cm_scache *scp; /* scache of open file */ + struct cm_user *userp; /* user that opened the file + originally (used to close + the file if session is + terminated) */ long offset; /* our file pointer */ smb_ioctl_t *ioctlp; /* ptr to ioctl structure */ /* Under NT, we may need to know the @@ -511,6 +515,9 @@ extern smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags); extern void smb_ReleaseFID(smb_fid_t *fidp); +extern long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp, + afs_uint32 dosTime); + extern int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, char **pathNamep); extern int smb_FindShareCSCPolicy(char *shareName); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index fd98701ad..2adfb8056 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -842,7 +842,7 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * if (uidp) { /* already there, so don't create a new one */ unp = uidp->unp; userp = unp->userp; - newUid = (unsigned short)uidp->userID; /* For some reason these are different types!*/ + newUid = uidp->userID; osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern)); osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid); smb_ReleaseUID(uidp); @@ -2364,6 +2364,9 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) /* save a pointer to the vnode */ fidp->scp = scp; + /* and the user */ + cm_HoldUser(userp); + fidp->userp = userp; /* compute open mode */ if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD; @@ -4742,6 +4745,9 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) /* save a pointer to the vnode */ fidp->scp = scp; + /* also the user */ + cm_HoldUser(userp); + fidp->userp = userp; /* compute open mode */ if (openMode != 1) @@ -5931,6 +5937,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); osi_assert(fidp); + /* save a reference to the user */ + cm_HoldUser(userp); + fidp->userp = userp; + /* If we are restricting sharing, we should do so with a suitable share lock. */ if (scp->fileType == CM_SCACHETYPE_FILE && @@ -6519,6 +6529,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); osi_assert(fidp); + /* save a reference to the user */ + cm_HoldUser(userp); + fidp->userp = userp; + /* If we are restricting sharing, we should do so with a suitable share lock. */ if (scp->fileType == CM_SCACHETYPE_FILE &&