xref: /haiku/src/add-ons/kernel/file_systems/nfs4/Cookie.cpp (revision 00a8558cc75d9aee84f6d9b34c28d6706952558c)
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 	fLocks(NULL),
138 	fLockOwners(NULL)
139 {
140 	mutex_init(&fLocksLock, NULL);
141 	mutex_init(&fOwnerLock, NULL);
142 }
143 
144 
145 OpenFileCookie::~OpenFileCookie()
146 {
147 	mutex_destroy(&fLocksLock);
148 	mutex_destroy(&fOwnerLock);
149 }
150 
151 
152 LockOwner*
153 OpenFileCookie::GetLockOwner(uint32 owner)
154 {
155 	LockOwner* current = fLockOwners;
156 	while (current != NULL) {
157 		if (current->fOwner == owner)
158 			return current;
159 
160 		current = current->fNext;
161 	}
162 
163 	current = new LockOwner(owner);
164 	if (current == NULL)
165 		return NULL;
166 
167 	current->fClientId = fClientId;
168 	current->fNext = fLockOwners;
169 	if (fLockOwners != NULL)
170 		fLockOwners->fPrev = current;
171 	fLockOwners = current;
172 
173 	return current;
174 }
175 
176 
177 // Caller must hold fLocksLock
178 void
179 OpenFileCookie::AddLock(LockInfo* lock)
180 {
181 	lock->fNext = fLocks;
182 	fLocks = lock;
183 }
184 
185 
186 // Caller must hold fLocksLock
187 void
188 OpenFileCookie::RemoveLock(LockInfo* lock, LockInfo* prev)
189 {
190 	if (prev != NULL)
191 		prev->fNext = lock->fNext;
192 	else
193 		fLocks = lock->fNext;
194 }
195 
196 
197 void
198 OpenFileCookie::DeleteLock(LockInfo* lock)
199 {
200 	MutexLocker _(fOwnerLock);
201 
202 	LockOwner* owner = lock->fOwner;
203 	delete lock;
204 
205 	if (owner->fUseCount == 0) {
206 		if (owner->fPrev)
207 			owner->fPrev->fNext = owner->fNext;
208 		else
209 			fLockOwners = owner->fNext;
210 		if (owner->fNext)
211 			owner->fNext->fPrev = owner->fPrev;
212 
213 		_ReleaseLockOwner(owner);
214 		delete owner;
215 	}
216 }
217 
218 
219 status_t
220 OpenFileCookie::_ReleaseLockOwner(LockOwner* owner)
221 {
222 	Request request(fFileSystem->Server());
223 	RequestBuilder& req = request.Builder();
224 
225 	req.ReleaseLockOwner(this, owner);
226 
227 	status_t result = request.Send();
228 	if (result != B_OK)
229 		return result;
230 
231 	ReplyInterpreter &reply = request.Reply();
232 
233 	return reply.ReleaseLockOwner();
234 }
235 
236