]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/Mmapped/MmappedFile.cc
b4a70d9359a7c393b6631b015b176cbd7bbd1589
4 * DEBUG: section 47 Store Directory Routines
9 #include "DiskIO/IORequestor.h"
10 #include "DiskIO/Mmapped/MmappedFile.h"
11 #include "DiskIO/ReadRequest.h"
12 #include "DiskIO/WriteRequest.h"
26 CBDATA_CLASS_INIT(MmappedFile
);
28 // helper class to deal with mmap(2) offset alignment and other low-level specs
32 Mmapping(int fd
, size_t length
, int prot
, int flags
, off_t offset
);
35 void *map(); ///< calls mmap(2); returns usable buffer or nil on failure
36 bool unmap(); ///< unmaps previously mapped buffer, if any
39 const int fd
; ///< descriptor of the mmapped file
40 const size_t length
; ///< user-requested data length, needed for munmap
41 const int prot
; ///< mmap(2) "protection" flags
42 const int flags
; ///< other mmap(2) flags
43 const off_t offset
; ///< user-requested data offset
45 off_t delta
; ///< mapped buffer increment to hit user offset
46 void *buf
; ///< buffer returned by mmap, needed for munmap
50 MmappedFile::operator new(size_t sz
)
52 CBDATA_INIT_TYPE(MmappedFile
);
53 MmappedFile
*result
= cbdataAlloc(MmappedFile
);
54 /* Mark result as being owned - we want the refcounter to do the delete
60 MmappedFile::operator delete(void *address
)
62 MmappedFile
*t
= static_cast<MmappedFile
*>(address
);
66 MmappedFile::MmappedFile(char const *aPath
): fd(-1),
67 minOffset(0), maxOffset(-1), error_(false)
70 path_
= xstrdup(aPath
);
71 debugs(79,5, HERE
<< this << ' ' << path_
);
74 MmappedFile::~MmappedFile()
80 // XXX: almost a copy of BlockingFile::open
82 MmappedFile::open(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
86 /* Simulate async calls */
87 fd
= file_open(path_
, flags
);
88 ioRequestor
= callback
;
91 debugs(79,3, HERE
<< "open error: " << xstrerror());
95 debugs(79,3, HERE
<< "FD " << fd
);
97 // setup mapping boundaries
99 if (fstat(fd
, &sb
) == 0)
100 maxOffset
= sb
.st_size
; // we do not expect it to change
103 callback
->ioCompletedNotification();
107 * Alias for MmappedFile::open(...)
108 \copydoc MmappedFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
111 MmappedFile::create(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
113 /* We use the same logic path for open */
114 open(flags
, mode
, callback
);
117 void MmappedFile::doClose()
122 --store_open_disk_fd
;
129 debugs(79, 3, HERE
<< this << " closing for " << ioRequestor
);
131 assert(ioRequestor
!= NULL
);
132 ioRequestor
->closeCompleted();
136 MmappedFile::canRead() const
142 MmappedFile::canWrite() const
148 MmappedFile::error() const
154 MmappedFile::read(ReadRequest
*aRequest
)
156 debugs(79,3, HERE
<< "(FD " << fd
<< ", " << aRequest
->len
<< ", " <<
157 aRequest
->offset
<< ")");
160 assert(ioRequestor
!= NULL
);
161 assert(aRequest
->len
> 0); // TODO: work around mmap failures on zero-len?
162 assert(aRequest
->offset
>= 0);
163 assert(!error_
); // TODO: propagate instead?
165 assert(minOffset
< 0 || minOffset
<= aRequest
->offset
);
166 assert(maxOffset
< 0 || static_cast<uint64_t>(aRequest
->offset
+ aRequest
->len
) <= static_cast<uint64_t>(maxOffset
));
168 Mmapping
mapping(fd
, aRequest
->len
, PROT_READ
, MAP_PRIVATE
| MAP_NORESERVE
,
172 if (void *buf
= mapping
.map()) {
173 memcpy(aRequest
->buf
, buf
, aRequest
->len
);
174 done
= mapping
.unmap();
178 const ssize_t rlen
= error_
? -1 : (ssize_t
)aRequest
->len
;
179 const int errflag
= error_
? DISK_ERROR
:DISK_OK
;
180 ioRequestor
->readCompleted(aRequest
->buf
, rlen
, errflag
, aRequest
);
184 MmappedFile::write(WriteRequest
*aRequest
)
186 debugs(79,3, HERE
<< "(FD " << fd
<< ", " << aRequest
->len
<< ", " <<
187 aRequest
->offset
<< ")");
190 assert(ioRequestor
!= NULL
);
191 assert(aRequest
->len
> 0); // TODO: work around mmap failures on zero-len?
192 assert(aRequest
->offset
>= 0);
193 assert(!error_
); // TODO: propagate instead?
195 assert(minOffset
< 0 || minOffset
<= aRequest
->offset
);
196 assert(maxOffset
< 0 || static_cast<uint64_t>(aRequest
->offset
+ aRequest
->len
) <= static_cast<uint64_t>(maxOffset
));
198 const ssize_t written
=
199 pwrite(fd
, aRequest
->buf
, aRequest
->len
, aRequest
->offset
);
201 debugs(79, DBG_IMPORTANT
, HERE
<< "error: " << xstrerr(errno
));
203 } else if (static_cast<size_t>(written
) != aRequest
->len
) {
204 debugs(79, DBG_IMPORTANT
, HERE
<< "problem: " << written
<< " < " << aRequest
->len
);
208 if (aRequest
->free_func
)
209 (aRequest
->free_func
)(const_cast<char*>(aRequest
->buf
)); // broken API?
212 debugs(79,5, HERE
<< "wrote " << aRequest
->len
<< " to FD " << fd
<< " at " << aRequest
->offset
);
217 const ssize_t rlen
= error_
? 0 : (ssize_t
)aRequest
->len
;
218 const int errflag
= error_
? DISK_ERROR
:DISK_OK
;
219 ioRequestor
->writeCompleted(errflag
, rlen
, aRequest
);
222 /// we only support blocking I/O
224 MmappedFile::ioInProgress() const
229 Mmapping::Mmapping(int aFd
, size_t aLength
, int aProt
, int aFlags
, off_t anOffset
):
230 fd(aFd
), length(aLength
), prot(aProt
), flags(aFlags
), offset(anOffset
),
235 Mmapping::~Mmapping()
244 // mmap(2) requires that offset is a multiple of the page size
245 static const int pageSize
= getpagesize();
246 delta
= offset
% pageSize
;
248 buf
= mmap(NULL
, length
+ delta
, prot
, flags
, fd
, offset
- delta
);
250 if (buf
== MAP_FAILED
) {
251 const int errNo
= errno
;
252 debugs(79,3, HERE
<< "error FD " << fd
<< "mmap(" << length
<< '+' <<
253 delta
<< ", " << offset
<< '-' << delta
<< "): " << xstrerr(errNo
));
258 return static_cast<char*>(buf
) + delta
;
264 debugs(79,9, HERE
<< "FD " << fd
<<
265 " munmap(" << buf
<< ", " << length
<< '+' << delta
<< ')');
267 if (!buf
) // forgot or failed to map
270 const bool error
= munmap(buf
, length
+ delta
) != 0;
272 const int errNo
= errno
;
273 debugs(79,3, HERE
<< "error FD " << fd
<<
274 " munmap(" << buf
<< ", " << length
<< '+' << delta
<< "): " <<
275 "): " << xstrerr(errNo
));
281 // TODO: check MAP_NORESERVE, consider MAP_POPULATE and MAP_FIXED