| OLD | NEW |
| 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 */ | 4 */ |
| 5 #include "nacl_io/kernel_object.h" | 5 #include "nacl_io/kernel_object.h" |
| 6 | 6 |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <pthread.h> | 10 #include <pthread.h> |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <map> | 13 #include <map> |
| 14 #include <string> | 14 #include <string> |
| 15 #include <vector> | 15 #include <vector> |
| 16 | 16 |
| 17 #include "nacl_io/kernel_handle.h" | 17 #include "nacl_io/kernel_handle.h" |
| 18 #include "nacl_io/mount.h" | 18 #include "nacl_io/mount.h" |
| 19 #include "nacl_io/mount_node.h" | 19 #include "nacl_io/mount_node.h" |
| 20 | 20 |
| 21 #include "sdk_util/auto_lock.h" | 21 #include "sdk_util/auto_lock.h" |
| 22 #include "sdk_util/ref_object.h" | 22 #include "sdk_util/ref_object.h" |
| 23 #include "sdk_util/scoped_ref.h" | 23 #include "sdk_util/scoped_ref.h" |
| 24 | 24 |
| 25 KernelObject::KernelObject() { | 25 KernelObject::KernelObject() { |
| 26 pthread_mutex_init(&mount_lock_, NULL); | |
| 27 pthread_mutex_init(&handle_lock_, NULL); | |
| 28 pthread_mutex_init(&cwd_lock_,NULL); | |
| 29 | |
| 30 cwd_ = "/"; | 26 cwd_ = "/"; |
| 31 } | 27 } |
| 32 | 28 |
| 33 KernelObject::~KernelObject() { | 29 KernelObject::~KernelObject() {}; |
| 34 pthread_mutex_destroy(&cwd_lock_); | |
| 35 pthread_mutex_destroy(&handle_lock_); | |
| 36 pthread_mutex_destroy(&mount_lock_); | |
| 37 } | |
| 38 | 30 |
| 39 Error KernelObject::AttachMountAtPath(const ScopedMount& mnt, | 31 Error KernelObject::AttachMountAtPath(const ScopedMount& mnt, |
| 40 const std::string& path) { | 32 const std::string& path) { |
| 41 std::string abs_path = GetAbsParts(path).Join(); | 33 std::string abs_path = GetAbsParts(path).Join(); |
| 42 | 34 |
| 43 AutoLock lock(&mount_lock_); | 35 AUTO_LOCK(mount_lock_); |
| 44 if (mounts_.find(abs_path) != mounts_.end()) | 36 if (mounts_.find(abs_path) != mounts_.end()) |
| 45 return EBUSY; | 37 return EBUSY; |
| 46 | 38 |
| 47 mounts_[abs_path] = mnt; | 39 mounts_[abs_path] = mnt; |
| 48 return 0; | 40 return 0; |
| 49 } | 41 } |
| 50 | 42 |
| 51 Error KernelObject::DetachMountAtPath(const std::string& path) { | 43 Error KernelObject::DetachMountAtPath(const std::string& path) { |
| 52 std::string abs_path = GetAbsParts(path).Join(); | 44 std::string abs_path = GetAbsParts(path).Join(); |
| 53 | 45 |
| 54 AutoLock lock(&mount_lock_); | 46 AUTO_LOCK(mount_lock_); |
| 55 MountMap_t::iterator it = mounts_.find(abs_path); | 47 MountMap_t::iterator it = mounts_.find(abs_path); |
| 56 if (mounts_.end() == it) | 48 if (mounts_.end() == it) |
| 57 return EINVAL; | 49 return EINVAL; |
| 58 | 50 |
| 59 // It is only legal to unmount if there are no open references | 51 // It is only legal to unmount if there are no open references |
| 60 if (it->second->RefCount() != 1) | 52 if (it->second->RefCount() != 1) |
| 61 return EBUSY; | 53 return EBUSY; |
| 62 | 54 |
| 63 mounts_.erase(it); | 55 mounts_.erase(it); |
| 64 return 0; | 56 return 0; |
| 65 } | 57 } |
| 66 | 58 |
| 67 // Uses longest prefix to find the mount for the give path, then | 59 // Uses longest prefix to find the mount for the give path, then |
| 68 // acquires the mount and returns it with a relative path. | 60 // acquires the mount and returns it with a relative path. |
| 69 Error KernelObject::AcquireMountAndRelPath(const std::string& path, | 61 Error KernelObject::AcquireMountAndRelPath(const std::string& path, |
| 70 ScopedMount* out_mount, | 62 ScopedMount* out_mount, |
| 71 Path* rel_parts) { | 63 Path* rel_parts) { |
| 72 Path abs_parts = GetAbsParts(path); | 64 Path abs_parts = GetAbsParts(path); |
| 73 | 65 |
| 74 out_mount->reset(NULL); | 66 out_mount->reset(NULL); |
| 75 *rel_parts = Path(); | 67 *rel_parts = Path(); |
| 76 | 68 |
| 77 AutoLock lock(&mount_lock_); | 69 AUTO_LOCK(mount_lock_); |
| 78 | 70 |
| 79 // Find longest prefix | 71 // Find longest prefix |
| 80 size_t max = abs_parts.Size(); | 72 size_t max = abs_parts.Size(); |
| 81 for (size_t len = 0; len < abs_parts.Size(); len++) { | 73 for (size_t len = 0; len < abs_parts.Size(); len++) { |
| 82 MountMap_t::iterator it = mounts_.find(abs_parts.Range(0, max - len)); | 74 MountMap_t::iterator it = mounts_.find(abs_parts.Range(0, max - len)); |
| 83 if (it != mounts_.end()) { | 75 if (it != mounts_.end()) { |
| 84 rel_parts->Set("/"); | 76 rel_parts->Set("/"); |
| 85 rel_parts->Append(abs_parts.Range(max - len, max)); | 77 rel_parts->Append(abs_parts.Range(max - len, max)); |
| 86 | 78 |
| 87 *out_mount = it->second; | 79 *out_mount = it->second; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 106 return error; | 98 return error; |
| 107 | 99 |
| 108 error = (*out_mount)->Open(rel_parts, oflags, out_node); | 100 error = (*out_mount)->Open(rel_parts, oflags, out_node); |
| 109 if (error) | 101 if (error) |
| 110 return error; | 102 return error; |
| 111 | 103 |
| 112 return 0; | 104 return 0; |
| 113 } | 105 } |
| 114 | 106 |
| 115 Path KernelObject::GetAbsParts(const std::string& path) { | 107 Path KernelObject::GetAbsParts(const std::string& path) { |
| 116 AutoLock lock(&cwd_lock_); | 108 AUTO_LOCK(cwd_lock_); |
| 117 | 109 |
| 118 Path abs_parts(cwd_); | 110 Path abs_parts(cwd_); |
| 119 if (path[0] == '/') { | 111 if (path[0] == '/') { |
| 120 abs_parts = path; | 112 abs_parts = path; |
| 121 } else { | 113 } else { |
| 122 abs_parts = cwd_; | 114 abs_parts = cwd_; |
| 123 abs_parts.Append(path); | 115 abs_parts.Append(path); |
| 124 } | 116 } |
| 125 | 117 |
| 126 return abs_parts; | 118 return abs_parts; |
| 127 } | 119 } |
| 128 | 120 |
| 129 std::string KernelObject::GetCWD() { | 121 std::string KernelObject::GetCWD() { |
| 130 AutoLock lock(&cwd_lock_); | 122 AUTO_LOCK(cwd_lock_); |
| 131 std::string out = cwd_; | 123 std::string out = cwd_; |
| 132 | 124 |
| 133 return out; | 125 return out; |
| 134 } | 126 } |
| 135 | 127 |
| 136 Error KernelObject::SetCWD(const std::string& path) { | 128 Error KernelObject::SetCWD(const std::string& path) { |
| 137 std::string abs_path = GetAbsParts(path).Join(); | 129 std::string abs_path = GetAbsParts(path).Join(); |
| 138 | 130 |
| 139 ScopedMount mnt; | 131 ScopedMount mnt; |
| 140 ScopedMountNode node; | 132 ScopedMountNode node; |
| 141 | 133 |
| 142 Error error = AcquireMountAndNode(abs_path, O_RDONLY, &mnt, &node); | 134 Error error = AcquireMountAndNode(abs_path, O_RDONLY, &mnt, &node); |
| 143 if (error) | 135 if (error) |
| 144 return error; | 136 return error; |
| 145 | 137 |
| 146 if ((node->GetType() & S_IFDIR) == 0) | 138 if ((node->GetType() & S_IFDIR) == 0) |
| 147 return ENOTDIR; | 139 return ENOTDIR; |
| 148 | 140 |
| 149 AutoLock lock(&cwd_lock_); | 141 AUTO_LOCK(cwd_lock_); |
| 150 cwd_ = abs_path; | 142 cwd_ = abs_path; |
| 151 return 0; | 143 return 0; |
| 152 } | 144 } |
| 153 | 145 |
| 154 Error KernelObject::AcquireHandle(int fd, ScopedKernelHandle* out_handle) { | 146 Error KernelObject::AcquireHandle(int fd, ScopedKernelHandle* out_handle) { |
| 155 out_handle->reset(NULL); | 147 out_handle->reset(NULL); |
| 156 | 148 |
| 157 AutoLock lock(&handle_lock_); | 149 AUTO_LOCK(handle_lock_); |
| 158 if (fd < 0 || fd >= static_cast<int>(handle_map_.size())) | 150 if (fd < 0 || fd >= static_cast<int>(handle_map_.size())) |
| 159 return EBADF; | 151 return EBADF; |
| 160 | 152 |
| 161 *out_handle = handle_map_[fd]; | 153 *out_handle = handle_map_[fd]; |
| 162 if (out_handle) return 0; | 154 if (out_handle) return 0; |
| 163 | 155 |
| 164 return EBADF; | 156 return EBADF; |
| 165 } | 157 } |
| 166 | 158 |
| 167 int KernelObject::AllocateFD(const ScopedKernelHandle& handle) { | 159 int KernelObject::AllocateFD(const ScopedKernelHandle& handle) { |
| 168 AutoLock lock(&handle_lock_); | 160 AUTO_LOCK(handle_lock_); |
| 169 int id; | 161 int id; |
| 170 | 162 |
| 171 // If we can recycle and FD, use that first | 163 // If we can recycle and FD, use that first |
| 172 if (free_fds_.size()) { | 164 if (free_fds_.size()) { |
| 173 id = free_fds_.front(); | 165 id = free_fds_.front(); |
| 174 // Force lower numbered FD to be available first. | 166 // Force lower numbered FD to be available first. |
| 175 std::pop_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); | 167 std::pop_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); |
| 176 free_fds_.pop_back(); | 168 free_fds_.pop_back(); |
| 177 handle_map_[id] = handle; | 169 handle_map_[id] = handle; |
| 178 } else { | 170 } else { |
| 179 id = handle_map_.size(); | 171 id = handle_map_.size(); |
| 180 handle_map_.push_back(handle); | 172 handle_map_.push_back(handle); |
| 181 } | 173 } |
| 182 return id; | 174 return id; |
| 183 } | 175 } |
| 184 | 176 |
| 185 void KernelObject::FreeAndReassignFD(int fd, const ScopedKernelHandle& handle) { | 177 void KernelObject::FreeAndReassignFD(int fd, const ScopedKernelHandle& handle) { |
| 186 if (NULL == handle) { | 178 if (NULL == handle) { |
| 187 FreeFD(fd); | 179 FreeFD(fd); |
| 188 } else { | 180 } else { |
| 189 AutoLock lock(&handle_lock_); | 181 AUTO_LOCK(handle_lock_); |
| 190 | 182 |
| 191 // If the required FD is larger than the current set, grow the set | 183 // If the required FD is larger than the current set, grow the set |
| 192 if (fd >= handle_map_.size()) | 184 if (fd >= handle_map_.size()) |
| 193 handle_map_.resize(fd + 1, ScopedRef<KernelHandle>()); | 185 handle_map_.resize(fd + 1, ScopedRef<KernelHandle>()); |
| 194 | 186 |
| 195 handle_map_[fd] = handle; | 187 handle_map_[fd] = handle; |
| 196 } | 188 } |
| 197 } | 189 } |
| 198 | 190 |
| 199 void KernelObject::FreeFD(int fd) { | 191 void KernelObject::FreeFD(int fd) { |
| 200 AutoLock lock(&handle_lock_); | 192 AUTO_LOCK(handle_lock_); |
| 201 | 193 |
| 202 handle_map_[fd].reset(NULL); | 194 handle_map_[fd].reset(NULL); |
| 203 free_fds_.push_back(fd); | 195 free_fds_.push_back(fd); |
| 204 | 196 |
| 205 // Force lower numbered FD to be available first. | 197 // Force lower numbered FD to be available first. |
| 206 std::push_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); | 198 std::push_heap(free_fds_.begin(), free_fds_.end(), std::greater<int>()); |
| 207 } | 199 } |
| OLD | NEW |