xref: /haiku/src/system/kernel/device_manager/io_requests.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <io_requests.h>
7 
8 #include "IORequest.h"
9 
10 
11 // #pragma mark - static helpers
12 
13 
14 static status_t
15 transfer_io_request_data(io_request* request, void* buffer, size_t size,
16 	bool writeToRequest)
17 {
18 	if (writeToRequest == request->IsWrite()
19 		|| request->RemainingBytes() < size) {
20 		return B_BAD_VALUE;
21 	}
22 
23 	// lock the request buffer memory, if it is user memory
24 	IOBuffer* ioBuffer = request->Buffer();
25 	if (ioBuffer->IsUser() && !ioBuffer->IsMemoryLocked()) {
26 		status_t error = ioBuffer->LockMemory(request->TeamID(),
27 			!writeToRequest);
28 		if (error != B_OK)
29 			return error;
30 	}
31 
32 	// read/write
33 	off_t offset = request->Offset() + request->TransferredBytes();
34 	status_t error = writeToRequest
35 		? request->CopyData(buffer, offset, size)
36 		: request->CopyData(offset, buffer, size);
37 	if (error != B_OK)
38 		return error;
39 
40 	request->Advance(size);
41 	return B_OK;
42 }
43 
44 
45 // #pragma mark - public API
46 
47 
48 /*!	Returns whether the given I/O request is a write request. */
49 bool
50 io_request_is_write(const io_request* request)
51 {
52 	return request->IsWrite();
53 }
54 
55 
56 /*!	Returns whether the I/O request has VIP status. */
57 bool
58 io_request_is_vip(const io_request* request)
59 {
60 	return (request->Flags() & B_VIP_IO_REQUEST) != 0;
61 }
62 
63 
64 /*!	Returns the read/write offset of the given I/O request.
65 	This is the immutable offset the request was created with;
66 	read_from_io_request() and write_to_io_request() don't change it.
67 */
68 off_t
69 io_request_offset(const io_request* request)
70 {
71 	return request->Offset();
72 }
73 
74 
75 /*!	Returns the read/write length of the given I/O request.
76 	This is the immutable length the request was created with;
77 	read_from_io_request() and write_to_io_request() don't change it.
78 */
79 off_t
80 io_request_length(const io_request* request)
81 {
82 	return request->Length();
83 }
84 
85 
86 /*!	Reads data from the given I/O request into the given buffer and advances
87 	the request's transferred data pointer.
88 	Multiple calls to read_from_io_request() are allowed, but the total size
89 	must not exceed io_request_length(request).
90 */
91 status_t
92 read_from_io_request(io_request* request, void* buffer, size_t size)
93 {
94 	return transfer_io_request_data(request, buffer, size, false);
95 }
96 
97 
98 /*!	Writes data from the given buffer to the given I/O request and advances
99 	the request's transferred data pointer.
100 	Multiple calls to write_to_io_request() are allowed, but the total size
101 	must not exceed io_request_length(request).
102 */
103 status_t
104 write_to_io_request(io_request* request, const void* buffer, size_t size)
105 {
106 	return transfer_io_request_data(request, (void*)buffer, size, true);
107 }
108 
109 
110 /*!	Sets the given I/O request's status and notifies listeners that the request
111 	is finished.
112 */
113 void
114 notify_io_request(io_request* request, status_t status)
115 {
116 	request->SetStatusAndNotify(status);
117 }
118