1 /* 2 * Copyright 2018 Google, Inc 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBDM_LOOP_CONTROL_H_ 18 #define _LIBDM_LOOP_CONTROL_H_ 19 20 #include <chrono> 21 #include <string> 22 23 #include <android-base/unique_fd.h> 24 25 namespace android { 26 namespace dm { 27 28 class LoopControl final { 29 public: 30 LoopControl(); 31 32 // Attaches the file specified by 'file_fd' to the loop device specified 33 // by 'loopdev'. It is possible that in between allocating and attaching 34 // a loop device, another process attaches to the chosen loop device. If 35 // this happens, Attach() will retry for up to |timeout_ms|. The timeout 36 // should not be zero. 37 // 38 // The caller does not have to call WaitForFile(); it is implicitly called. 39 // The given |timeout_ms| covers both potential sources of timeout. 40 bool Attach(int file_fd, const std::chrono::milliseconds& timeout_ms, 41 std::string* loopdev) const; 42 43 // Detach the loop device given by 'loopdev' from the attached backing file. 44 bool Detach(const std::string& loopdev) const; 45 46 // Enable Direct I/O on a loop device. This requires kernel 4.9+. 47 static bool EnableDirectIo(int fd); 48 49 LoopControl(const LoopControl&) = delete; 50 LoopControl& operator=(const LoopControl&) = delete; 51 LoopControl& operator=(LoopControl&&) = default; 52 LoopControl(LoopControl&&) = default; 53 54 private: 55 bool FindFreeLoopDevice(std::string* loopdev) const; 56 57 static constexpr const char* kLoopControlDevice = "/dev/loop-control"; 58 59 android::base::unique_fd control_fd_; 60 }; 61 62 // Create a temporary loop device around a file descriptor or path. 63 class LoopDevice { 64 public: 65 // Create a loop device for the given file descriptor. It is closed when 66 // LoopDevice is destroyed only if auto_close is true. 67 LoopDevice(android::base::borrowed_fd fd, const std::chrono::milliseconds& timeout_ms, 68 bool auto_close = false); 69 // Create a loop device for the given file path. It will be opened for 70 // reading and writing and closed when the loop device is detached. 71 LoopDevice(const std::string& path, const std::chrono::milliseconds& timeout_ms); 72 ~LoopDevice(); 73 valid()74 bool valid() const { return valid_; } device()75 const std::string& device() const { return device_; } 76 77 LoopDevice(const LoopDevice&) = delete; 78 LoopDevice& operator=(const LoopDevice&) = delete; 79 LoopDevice& operator=(LoopDevice&&) = default; 80 LoopDevice(LoopDevice&&) = default; 81 82 private: 83 void Init(const std::chrono::milliseconds& timeout_ms); 84 85 android::base::borrowed_fd fd_; 86 android::base::unique_fd owned_fd_; 87 std::string device_; 88 LoopControl control_; 89 bool valid_ = false; 90 }; 91 92 } // namespace dm 93 } // namespace android 94 95 #endif /* _LIBDM_LOOP_CONTROL_H_ */ 96