xref: /haiku/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp (revision 62869605c565855e3293809a9974846fa50c423f)
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