1 /* 2 * Copyright 2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Paweł Dziepak, pdziepak@quarnos.org 7 */ 8 9 10 #include "Cookie.h" 11 12 #include "Inode.h" 13 #include "Request.h" 14 15 16 vint64 OpenFileCookie::fLastOwnerId = 0; 17 18 19 LockOwner::LockOwner(uint32 owner) 20 : 21 fSequence(0), 22 fOwner(owner), 23 fUseCount(0), 24 fNext(NULL), 25 fPrev(NULL) 26 { 27 memset(fStateId, 0, sizeof(fStateId)); 28 mutex_init(&fLock, NULL); 29 } 30 31 32 LockOwner::~LockOwner() 33 { 34 mutex_destroy(&fLock); 35 } 36 37 38 LockInfo::LockInfo(LockOwner* owner) 39 : 40 fOwner(owner) 41 { 42 fOwner->fUseCount++; 43 } 44 45 46 LockInfo::~LockInfo() 47 { 48 fOwner->fUseCount--; 49 } 50 51 52 bool 53 LockInfo::operator==(const struct flock& lock) const 54 { 55 bool eof = lock.l_len + lock.l_start == OFF_MAX; 56 uint64 start = static_cast<uint64>(lock.l_start); 57 uint64 len = static_cast<uint64>(lock.l_len); 58 59 return fStart == start && fLength == len || eof && fLength == UINT64_MAX; 60 } 61 62 63 Cookie::Cookie() 64 : 65 fRequests(NULL), 66 fSnoozeCancel(create_sem(1, NULL)) 67 { 68 acquire_sem(fSnoozeCancel); 69 mutex_init(&fRequestLock, NULL); 70 } 71 72 73 Cookie::~Cookie() 74 { 75 delete_sem(fSnoozeCancel); 76 mutex_destroy(&fRequestLock); 77 } 78 79 80 status_t 81 Cookie::RegisterRequest(RPC::Request* req) 82 { 83 RequestEntry* ent = new RequestEntry; 84 if (ent == NULL) 85 return B_NO_MEMORY; 86 87 MutexLocker _(fRequestLock); 88 ent->fRequest = req; 89 ent->fNext = fRequests; 90 fRequests = ent; 91 92 return B_OK; 93 } 94 95 96 status_t 97 Cookie::UnregisterRequest(RPC::Request* req) 98 { 99 MutexLocker _(fRequestLock); 100 RequestEntry* ent = fRequests; 101 RequestEntry* prev = NULL; 102 while (ent != NULL) { 103 if (ent->fRequest == req) { 104 if (prev == NULL) 105 fRequests = ent->fNext; 106 else 107 prev->fNext = ent->fNext; 108 delete ent; 109 } 110 111 prev = ent; 112 ent = ent->fNext; 113 } 114 115 return B_OK; 116 } 117 118 119 status_t 120 Cookie::CancelAll() 121 { 122 release_sem(fSnoozeCancel); 123 124 MutexLocker _(fRequestLock); 125 RequestEntry* ent = fRequests; 126 while (ent != NULL) { 127 fFilesystem->Server()->WakeCall(ent->fRequest); 128 ent = ent->fNext; 129 } 130 131 return B_OK; 132 } 133 134 135 OpenFileCookie::OpenFileCookie() 136 : 137 fLockOwners(NULL) 138 { 139 mutex_init(&fLocksLock, NULL); 140 mutex_init(&fOwnerLock, NULL); 141 } 142 143 144 OpenFileCookie::~OpenFileCookie() 145 { 146 mutex_destroy(&fLocksLock); 147 mutex_destroy(&fOwnerLock); 148 } 149 150 151 LockOwner* 152 OpenFileCookie::GetLockOwner(uint32 owner) 153 { 154 MutexLocker _(fOwnerLock); 155 156 LockOwner* current = fLockOwners; 157 while (current != NULL) { 158 if (current->fOwner == owner) 159 return current; 160 161 current = current->fNext; 162 } 163 164 current = new LockOwner(owner); 165 if (current == NULL) 166 return NULL; 167 168 current->fClientId = fClientId; 169 current->fNext = fLockOwners; 170 if (fLockOwners != NULL) 171 fLockOwners->fPrev = current; 172 fLockOwners = current; 173 174 return current; 175 } 176 177 178 // Caller must hold fLocksLock 179 void 180 OpenFileCookie::AddLock(LockInfo* lock) 181 { 182 lock->fNext = fLocks; 183 fLocks = lock; 184 } 185 186 187 // Caller must hold fLocksLock 188 void 189 OpenFileCookie::RemoveLock(LockInfo* lock, LockInfo* prev) 190 { 191 if (prev != NULL) 192 prev->fNext = lock->fNext; 193 else 194 fLocks = lock->fNext; 195 } 196 197 198 void 199 OpenFileCookie::DeleteLock(LockInfo* lock) 200 { 201 MutexLocker _(fOwnerLock); 202 203 LockOwner* owner = lock->fOwner; 204 delete lock; 205 206 if (owner->fUseCount == 0) { 207 if (owner->fPrev) 208 owner->fPrev->fNext = owner->fNext; 209 else 210 fLockOwners = owner->fNext; 211 if (owner->fNext) 212 owner->fNext->fPrev = owner->fPrev; 213 214 delete owner; 215 } 216 } 217 218