vfs: check userland buffers before reading them.
[haiku.git] / src / system / kernel / device_manager / IORequest.h
blob4601f7a70b8733913659bc90238abd0f4016e284
1 /*
2 * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
5 */
6 #ifndef IO_REQUEST_H
7 #define IO_REQUEST_H
10 #include <sys/uio.h>
12 #include <new>
14 #include <fs_interface.h>
16 #include <condition_variable.h>
17 #include <lock.h>
18 #include <util/DoublyLinkedList.h>
20 #include "dma_resources.h"
23 #define B_PHYSICAL_IO_REQUEST 0x01 /* buffer points to physical memory */
24 #define B_VIP_IO_REQUEST 0x02 /* used by the page writer -- make sure
25 allocations won't fail */
26 #define B_DELETE_IO_REQUEST 0x04 /* delete request when finished */
28 class DMABuffer;
29 struct IOOperation;
31 typedef struct IOOperation io_operation;
33 class IOBuffer : public DoublyLinkedListLinkImpl<IOBuffer> {
34 public:
35 static IOBuffer* Create(uint32 count, bool vip);
36 void Delete();
38 bool IsVirtual() const { return !fPhysical; }
39 bool IsPhysical() const { return fPhysical; }
40 bool IsUser() const { return fUser; }
42 void SetVecs(generic_size_t firstVecOffset,
43 const generic_io_vec* vecs, uint32 count,
44 generic_size_t length, uint32 flags);
46 void SetPhysical(bool physical)
47 { fPhysical = physical; }
48 void SetUser(bool user) { fUser = user; }
49 void SetLength(generic_size_t length)
50 { fLength = length; }
51 void SetVecCount(uint32 count) { fVecCount = count; }
53 generic_size_t Length() const { return fLength; }
55 generic_io_vec* Vecs() { return fVecs; }
56 generic_io_vec& VecAt(size_t index) { return fVecs[index]; }
57 size_t VecCount() const { return fVecCount; }
58 size_t Capacity() const { return fCapacity; }
60 status_t GetNextVirtualVec(void*& cookie, iovec& vector);
61 void FreeVirtualVecCookie(void* cookie);
63 status_t LockMemory(team_id team, bool isWrite);
64 void UnlockMemory(team_id team, bool isWrite);
65 bool IsMemoryLocked() const
66 { return fMemoryLocked; }
68 void Dump() const;
70 private:
71 IOBuffer();
72 ~IOBuffer();
73 // not implemented
74 void _UnlockMemory(team_id team, size_t count,
75 bool isWrite);
77 bool fUser;
78 bool fPhysical;
79 bool fVIP;
80 bool fMemoryLocked;
81 generic_size_t fLength;
82 size_t fVecCount;
83 size_t fCapacity;
84 generic_io_vec fVecs[1];
88 struct IORequest;
89 struct IORequestOwner;
92 class IORequestChunk {
93 public:
94 IORequestChunk();
95 virtual ~IORequestChunk();
97 IORequest* Parent() const { return fParent; }
98 void SetParent(IORequest* parent)
99 { fParent = parent; }
101 status_t Status() const { return fStatus; }
103 DoublyLinkedListLink<IORequestChunk>*
104 ListLink() { return &fListLink; }
106 protected:
107 void SetStatus(status_t status)
108 { fStatus = status; }
109 void ResetStatus()
110 { fStatus = 1; }
112 protected:
113 IORequest* fParent;
114 status_t fStatus;
116 public:
117 DoublyLinkedListLink<IORequestChunk> fListLink;
120 typedef DoublyLinkedList<IORequestChunk,
121 DoublyLinkedListMemberGetLink<IORequestChunk, &IORequestChunk::fListLink> >
122 IORequestChunkList;
125 struct IOOperation : IORequestChunk, DoublyLinkedListLinkImpl<IOOperation> {
126 public:
127 bool Finish();
128 // returns true, if it can be recycled
130 status_t Prepare(IORequest* request);
131 void SetOriginalRange(off_t offset,
132 generic_size_t length);
133 // also sets range
134 void SetRange(off_t offset, generic_size_t length);
136 void SetStatus(status_t status)
137 { IORequestChunk::SetStatus(status); }
139 off_t Offset() const;
140 generic_size_t Length() const;
141 off_t OriginalOffset() const
142 { return fOriginalOffset; }
143 generic_size_t OriginalLength() const
144 { return fOriginalLength; }
146 generic_size_t TransferredBytes() const
147 { return fTransferredBytes; }
148 void SetTransferredBytes(generic_size_t bytes)
149 { fTransferredBytes = bytes; }
151 generic_io_vec* Vecs() const;
152 uint32 VecCount() const;
154 void SetPartial(bool partialBegin, bool partialEnd);
155 bool HasPartialBegin() const
156 { return fPartialBegin; }
157 bool HasPartialEnd() const
158 { return fPartialEnd; }
159 bool IsWrite() const;
160 bool IsRead() const;
162 void SetBlockSize(generic_size_t blockSize)
163 { fBlockSize = blockSize; }
165 bool UsesBounceBuffer() const
166 { return fUsesBounceBuffer; }
167 void SetUsesBounceBuffer(bool uses)
168 { fUsesBounceBuffer = uses; }
170 DMABuffer* Buffer() const { return fDMABuffer; }
171 void SetBuffer(DMABuffer* buffer)
172 { fDMABuffer = buffer; }
174 void Dump() const;
176 protected:
177 void _PrepareVecs();
178 status_t _CopyPartialBegin(bool isWrite,
179 bool& partialBlockOnly);
180 status_t _CopyPartialEnd(bool isWrite);
182 DMABuffer* fDMABuffer;
183 off_t fOffset;
184 off_t fOriginalOffset;
185 generic_size_t fLength;
186 generic_size_t fOriginalLength;
187 generic_size_t fTransferredBytes;
188 generic_size_t fBlockSize;
189 uint16 fSavedVecIndex;
190 uint16 fSavedVecLength;
191 uint8 fPhase;
192 bool fPartialBegin;
193 bool fPartialEnd;
194 bool fUsesBounceBuffer;
198 typedef IOOperation io_operation;
199 typedef DoublyLinkedList<IOOperation> IOOperationList;
201 typedef struct IORequest io_request;
202 typedef status_t (*io_request_finished_callback)(void* data,
203 io_request* request, status_t status, bool partialTransfer,
204 generic_size_t transferEndOffset);
205 // TODO: Return type: status_t -> void
206 typedef status_t (*io_request_iterate_callback)(void* data,
207 io_request* request, bool* _partialTransfer);
210 struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
211 IORequest();
212 virtual ~IORequest();
214 static IORequest* Create(bool vip);
216 status_t Init(off_t offset, generic_addr_t buffer,
217 generic_size_t length, bool write,
218 uint32 flags);
219 status_t Init(off_t offset, const generic_io_vec* vecs,
220 size_t count, generic_size_t length,
221 bool write, uint32 flags)
222 { return Init(offset, 0, vecs, count,
223 length, write, flags); }
224 status_t Init(off_t offset,
225 generic_size_t firstVecOffset,
226 const generic_io_vec* vecs, size_t count,
227 generic_size_t length, bool write,
228 uint32 flags);
230 void SetOwner(IORequestOwner* owner)
231 { fOwner = owner; }
232 IORequestOwner* Owner() const { return fOwner; }
234 status_t CreateSubRequest(off_t parentOffset,
235 off_t offset, generic_size_t length,
236 IORequest*& subRequest);
237 void DeleteSubRequests();
239 void SetFinishedCallback(
240 io_request_finished_callback callback,
241 void* cookie);
242 void SetIterationCallback(
243 io_request_iterate_callback callback,
244 void* cookie);
245 io_request_finished_callback FinishedCallback(
246 void** _cookie = NULL) const;
248 status_t Wait(uint32 flags = 0, bigtime_t timeout = 0);
250 bool IsFinished() const
251 { return fStatus != 1
252 && fPendingChildren == 0; }
253 void NotifyFinished();
254 bool HasCallbacks() const;
255 void SetStatusAndNotify(status_t status);
257 void OperationFinished(IOOperation* operation,
258 status_t status, bool partialTransfer,
259 generic_size_t transferEndOffset);
260 void SubRequestFinished(IORequest* request,
261 status_t status, bool partialTransfer,
262 generic_size_t transferEndOffset);
263 void SetUnfinished();
265 generic_size_t RemainingBytes() const
266 { return fRemainingBytes; }
267 generic_size_t TransferredBytes() const
268 { return fTransferSize; }
269 bool IsPartialTransfer() const
270 { return fPartialTransfer; }
271 void SetTransferredBytes(bool partialTransfer,
272 generic_size_t transferredBytes);
274 void SetSuppressChildNotifications(bool suppress);
275 bool SuppressChildNotifications() const
276 { return fSuppressChildNotifications; }
278 bool IsWrite() const { return fIsWrite; }
279 bool IsRead() const { return !fIsWrite; }
280 team_id TeamID() const { return fTeam; }
281 thread_id ThreadID() const { return fThread; }
282 uint32 Flags() const { return fFlags; }
284 IOBuffer* Buffer() const { return fBuffer; }
285 off_t Offset() const { return fOffset; }
286 generic_size_t Length() const { return fLength; }
288 void SetOffset(off_t offset) { fOffset = offset; }
290 uint32 VecIndex() const { return fVecIndex; }
291 generic_size_t VecOffset() const { return fVecOffset; }
293 void Advance(generic_size_t bySize);
295 IORequest* FirstSubRequest();
296 IORequest* NextSubRequest(IORequest* previous);
298 void AddOperation(IOOperation* operation);
299 void RemoveOperation(IOOperation* operation);
301 status_t CopyData(off_t offset, void* buffer,
302 size_t size);
303 status_t CopyData(const void* buffer, off_t offset,
304 size_t size);
305 status_t ClearData(off_t offset, generic_size_t size);
307 void Dump() const;
309 private:
310 status_t _CopyData(void* buffer, off_t offset,
311 size_t size, bool copyIn);
312 static status_t _CopySimple(void* bounceBuffer,
313 generic_addr_t external, size_t size,
314 team_id team, bool copyIn);
315 static status_t _CopyPhysical(void* bounceBuffer,
316 generic_addr_t external, size_t size,
317 team_id team, bool copyIn);
318 static status_t _CopyUser(void* bounceBuffer,
319 generic_addr_t external, size_t size,
320 team_id team, bool copyIn);
321 static status_t _ClearDataSimple(generic_addr_t external,
322 generic_size_t size, team_id team);
323 static status_t _ClearDataPhysical(generic_addr_t external,
324 generic_size_t size, team_id team);
325 static status_t _ClearDataUser(generic_addr_t external,
326 generic_size_t size, team_id team);
328 mutex fLock;
329 IORequestOwner* fOwner;
330 IOBuffer* fBuffer;
331 off_t fOffset;
332 generic_size_t fLength;
333 generic_size_t fTransferSize;
334 // After all subrequests/operations have
335 // finished, number of contiguous bytes at
336 // the beginning of the request that have
337 // actually been transferred.
338 generic_size_t fRelativeParentOffset;
339 // offset of this request relative to its
340 // parent
341 IORequestChunkList fChildren;
342 int32 fPendingChildren;
343 uint32 fFlags;
344 team_id fTeam;
345 thread_id fThread;
346 bool fIsWrite;
347 bool fPartialTransfer;
348 bool fSuppressChildNotifications;
349 bool fIsNotified;
351 io_request_finished_callback fFinishedCallback;
352 void* fFinishedCookie;
353 io_request_iterate_callback fIterationCallback;
354 void* fIterationCookie;
355 ConditionVariable fFinishedCondition;
357 // these are for iteration
358 uint32 fVecIndex;
359 generic_size_t fVecOffset;
360 generic_size_t fRemainingBytes;
364 typedef DoublyLinkedList<IORequest> IORequestList;
367 #endif // IO_REQUEST_H