1 // Copyright (C) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Copyright 2012 Google Inc. All Rights Reserved.
16 // Author: [email protected] (Scott Banachowski)
17 //
18 #include "icing/legacy/index/icing-mmapper.h"
19
20 #include <sys/mman.h>
21
22 #include <cerrno>
23 #include <cstring>
24
25 #include "icing/legacy/core/icing-string-util.h"
26 #include "icing/legacy/index/icing-filesystem.h"
27 #include "icing/util/logging.h"
28
29 namespace icing {
30 namespace lib {
31
IcingMMapper(bool read_only,int flags)32 IcingMMapper::IcingMMapper(bool read_only, int flags)
33 : address_(nullptr),
34 len_(0),
35 flags_(flags),
36 location_(0),
37 mmap_len_(0),
38 mmap_result_(nullptr),
39 read_only_(read_only) {}
40
IcingMMapper(int fd,bool read_only,uint64_t location,size_t size,int flags)41 IcingMMapper::IcingMMapper(int fd, bool read_only, uint64_t location,
42 size_t size, int flags)
43 : address_(nullptr),
44 len_(0),
45 flags_(flags),
46 location_(0),
47 mmap_len_(0),
48 mmap_result_(nullptr),
49 read_only_(read_only) {
50 DoMapping(fd, location, size);
51 }
52
DoMapping(int fd,uint64_t location,size_t size)53 void IcingMMapper::DoMapping(int fd, uint64_t location, size_t size) {
54 uint64_t aligned_offset =
55 (location / system_page_size()) * system_page_size();
56 size_t alignment_adjustment = location - aligned_offset;
57 size_t mmap_len = alignment_adjustment + size;
58
59 int prot = read_only_ ? (PROT_READ) : (PROT_READ | PROT_WRITE);
60
61 mmap_result_ = mmap(nullptr, mmap_len, prot, flags_, fd, aligned_offset);
62
63 if (mmap_result_ != MAP_FAILED) {
64 len_ = size;
65 location_ = location;
66 mmap_len_ = mmap_len;
67 address_ = reinterpret_cast<uint8_t *>(mmap_result_) + alignment_adjustment;
68 } else {
69 const char *errstr = strerror(errno);
70 ICING_LOG(ERROR) << "Could not mmap file for reading: " << errstr;
71 mmap_result_ = nullptr;
72 }
73 }
74
Remap(int fd,uint64_t location,size_t size)75 bool IcingMMapper::Remap(int fd, uint64_t location, size_t size) {
76 Unmap();
77 DoMapping(fd, location, size);
78 return is_valid();
79 }
80
Unmap()81 void IcingMMapper::Unmap() {
82 if (mmap_result_ != nullptr) {
83 munmap(mmap_result_, mmap_len_);
84 }
85 address_ = nullptr;
86 len_ = 0;
87 location_ = 0;
88 mmap_len_ = 0;
89 mmap_result_ = nullptr;
90 }
91
~IcingMMapper()92 IcingMMapper::~IcingMMapper() { Unmap(); }
93
Sync()94 bool IcingMMapper::Sync() {
95 if (is_valid() && !read_only_) {
96 if (msync(mmap_result_, mmap_len_, MS_SYNC) != 0) {
97 ICING_LOG(ERROR) << "msync failed: " << strerror(errno);
98 return false;
99 }
100 }
101 return true;
102 }
103
104 } // namespace lib
105 } // namespace icing
106