Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add mount sources for a MountNode (inode)

Split abstact base mount.h and mount_mem.h
Add mount_mem test.

BUG=122229
R=binji@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9956156

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135033 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information...
commit 0858b6bd24431963897d5e3ea547c499b55c4398 1 parent 0dda1bc
noelallen@google.com authored
View
409 native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc
@@ -2,290 +2,291 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
-#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string>
+#include <unistd.h>
-#include <vector>
-
+#include "mount.h"
#include "mount_mem.h"
+#include "mount_node.h"
+#include "mount_node_dir.h"
+#include "mount_node_mem.h"
#include "path.h"
-#include "util/simple_auto_lock.h"
-
-static const size_t s_blksize = 1024;
-
-class MountNodeMem {
- public:
- MountNodeMem(int ino) {
- ino_ = ino;
- ref_count_ = 0;
- data_ = NULL;
- memset(&stat_, 0, sizeof(stat_));
- Resize(s_blksize);
- };
-
- size_t Size() const {
- return stat_.st_size;
- }
- void Resize(size_t size) {
- size_t cap = blocks_;
- size_t req = (size + s_blksize - 1) / s_blksize;
-
- if ((req > cap) || (req < (cap / 2))) {
- char *newdata = (char *) malloc(req * s_blksize);
- memcpy(newdata, data_, size);
- free(data_);
- stat_.st_size = size;
- data_ = newdata;
- blocks_ = req;
- }
- }
+#include "auto_lock.h"
+#include "ref_object.h"
- int ino_;
- int ref_count_;
- struct stat stat_;
- void *data_;
- size_t blocks_;
- pthread_mutex_t lock_;
-};
+// TODO(noelallen) : Grab/Redefine these in the kernel object once available.
+#define USR_ID 1002
+#define GRP_ID 1003
-MountMem::MountMem() {}
-MountMem::~MountMem() {}
+MountMem::MountMem()
+ : MountFactory(),
+ root_(NULL),
+ max_ino_(0) {
+}
-int MountMem::AddDirEntry(MountMemNode* dir_node, MountMemNode* obj_node, const char *name) {
- if (strlen(name > 255)) {
- errno = EINVAL;
- return -1;
- }
+bool MountMem::Init(int dev, StringMap_t& args) {
+ dev_ = dev;
+ root_ = AllocatePath(_S_IREAD | _S_IWRITE);
+ return (bool) (root_ != NULL);
+}
- struct dirent* d = (struct dirent *) dir_node->data_;
- size_t cnt = dir_node->Size() / sizeof(struct dirent);
- size_t off;
+void MountMem::Destroy() {
+ if (root_)
+ root_->Release();
+ root_ = NULL;
+}
- // Find a free location
- for (off = 0; off < cnt; off++) {
- if (d->d_name[0] == 0) break;
- d++;
- }
+MountNode* MountMem::AllocatePath(int mode) {
+ ino_t ino = AllocateINO();
- // Otherwise regrow and take the last spot.
- if (off == cnt) {
- dir_node->Resize(dir_node->Size() + sizeof(struct dirent));
- d = &((struct dirent *) dir_node->data_)[off];
+ MountNode *ptr = new MountNodeDir(this, ino, dev_);
+ if (!ptr->Init(mode, 1002, 1003)) {
+ ptr->Release();
+ FreeINO(ino);
+ return NULL;
}
-
- strcpy(d->d_name, name);
- d->d_ino = obj_node->ino_;
- d->d_reclen = sizeof(dirent);
- d->d_off = off * sizeof(dirent);
-
- // Add a ref_count_ and link count for the directory
- obj_node->Acquire();
- obj_node->stat_.st_nlink++;
- return 0;
+ return ptr;
}
+MountNode* MountMem::AllocateData(int mode) {
+ ino_t ino = AllocateINO();
+ MountNode* ptr = new MountNodeMem(this, ino, dev_);
+ if (!ptr->Init(mode, getuid(), getgid())) {
+ ptr->Release();
+ FreeINO(ino);
+ return NULL;
+ }
+ return ptr;
+}
+void MountMem::ReleaseNode(MountNode* node) {
+ node->Release();
+}
-int MountMem::DelDirEntry_locked(int dir_ino, const char *name) {
- MountMemNode* dir_node = inodes_.At(dir_ino);
- struct dirent* d = (struct dirent *) dir_node->data_;
- size_t cnt = dir_node->Size() / sizeof(struct dirent);
- size_t off = 0;
+int MountMem::AllocateINO() {
+ const int INO_CNT = 8;
- // Find a free location
- for (off = 0; off < cnt; off++) {
- if (!strcmp(d->d_name, name)) {
- d->d_name[0] = 0;
- obj_node->stat_.st_nlink--;
- if (0 == --obj_node->ref_count_) FreeNode(obj_node->ino_);
- dir_node->ref_count_--;
- return 0;
+ // If we run out of INO numbers, then allocate 8 more
+ if (inos_.size() == 0) {
+ max_ino_ += INO_CNT;
+ // Add eight more to the stack in reverse order, offset by 1
+ // since '0' refers to no INO.
+ for (int a = 0; a < INO_CNT; a++) {
+ inos_.push_back(max_ino_ - a);
}
}
- errno = ENOENT;
- return -1;
+ // Return the INO at the top of the stack.
+ int val = inos_.back();
+ inos_.pop_back();
+ return val;
}
-MountNodeMem* MountMem::AcquireNode(int ino) {
- SimpleAutoLock lock(&lock_);
- MountNodeMem *node = inodes_.At(ino);
- if (node) node->ref_count_++;
- return node;
+void MountMem::FreeINO(int ino) {
+ inos_.push_back(ino);
}
-void MountMem::ReleaseNode(MountMemNode* node) {
- if (node) {
- SimpleAutoLock lock(&lock_);
- if (--node->ref_count_) inodes_.Free(node->ino_);
+MountNode* MountMem::FindNode(const Path& path, int type) {
+ MountNode* node = root_;
+
+ // If there is no root there, we have an error.
+ if (node == NULL) {
+ errno = ENOTDIR;
+ return NULL;
}
-}
-void MountMem::Init(void) {
- int root = inodes_.Alloc();
+ // We are expecting an "absolute" path from this mount point.
+ if (!path.IsAbsolute()) {
+ errno = EINVAL;
+ return NULL;
+ }
- assert(root == 0);
- AddDirEntry(root, root, "/");
-}
+ // Starting at the root, traverse the path parts.
+ for (size_t index = 1; node && index < path.Size(); index++) {
+ // If not a directory, then we have an error so return.
+ if (!node->IsaDir()) {
+ errno = ENOTDIR;
+ return NULL;
+ }
-int MountMem::Mkdir(const std::string& path, mode_t mode, struct stat *buf) {
- SimpleAutoLock lock(&lock_);
+ // Find the child node
+ node = node->FindChild(path.Part(index));
+ }
- int ino = AcquireNode(path);
+ // node should be root, a found child, or a failed 'FindChild'
+ // which already has the correct errno set.
+ if (NULL == node) return NULL;
- // Make sure it doesn't already exist.
- child = GetMemNode(path);
- if (child) {
- errno = EEXIST;
- return -1;
- }
- // Get the parent node.
- int parent_slot = GetParentSlot(path);
- if (parent_slot == -1) {
- errno = ENOENT;
- return -1;
- }
- parent = slots_.At(parent_slot);
- if (!parent->is_dir()) {
+ // If a directory is expected, but it's not a directory, then fail.
+ if ((type & _S_IFDIR) && !node->IsaDir()) {
errno = ENOTDIR;
- return -1;
+ return NULL;
}
- // Create a new node
- int slot = slots_.Alloc();
- child = slots_.At(slot);
- child->set_slot(slot);
- child->set_mount(this);
- child->set_is_dir(true);
- Path p(path);
- child->set_name(p.Last());
- child->set_parent(parent_slot);
- parent->AddChild(slot);
- if (!buf) {
- return 0;
+ // If a file is expected, but it's not a file, then fail.
+ if ((type & _S_IFREG) && node->IsaDir()) {
+ errno = EISDIR;
+ return NULL;
}
- return Stat(slot, buf);
-}
-
-int MountMem::Rmdir(int node) {
+ // We now have a valid object of the expected type, so return it.
+ return node;
}
-int MountMem::Chmod(int ino, int mode) {
- MountMemNode* node = AcquireNode(ino);
+MountNode* MountMem::Open(const Path& path, int mode) {
+ AutoLock lock(&lock_);
+ MountNode* node = FindNode(path);
if (NULL == node) {
- errno = BADF;
- return -1;
+ // Now first find the parent directory to see if we can add it
+ MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
+ if (NULL == parent) return NULL;
+
+ // If the node does not exist and we can't create it, fail
+ if ((mode & O_CREAT) == 0) return NULL;
+
+ // Otherwise, create it with a single refernece
+ mode = OpenModeToPermission(mode);
+ node = AllocateData(mode);
+ if (NULL == node) return NULL;
+
+ if (parent->AddChild(path.Filename(), node) == -1) {
+ // Or if it fails, release it
+ node->Release();
+ return NULL;
+ }
+ return node;
}
- node->stat_.st_mode = mode;
- ReleaseNode(node);
- return 0;
-}
-
-int MountMem::Stat(int ino, struct stat *buf) {
- MountMemNode* node = AcquireNode(ino);
+ // If we were expected to create it exclusively, fail
+ if (mode & O_EXCL) {
+ errno = EEXIST;
+ return NULL;
+ }
- if (NULL == node) {
- errno = BADF;
- return -1;
+ // Verify we got the requested permisions.
+ int req_mode = OpenModeToPermission(mode);
+ int obj_mode = node->GetMode() & OpenModeToPermission(O_RDWR);
+ if ((obj_mode & req_mode) != req_mode) {
+ errno = EACCES;
+ return NULL;
}
- memcpy(buf, node->stat_, sizeof(struct stat));
+ // We opened it, so ref count it before passing it back.
+ node->Acquire();
+ return node;
+}
+
+int MountMem::Close(MountNode* node) {
+ AutoLock lock(&lock_);
+ node->Close();
ReleaseNode(node);
return 0;
}
-int MountMem::Fsync(int ino) {
- // Acquire the node in case he node
- MountMemNode* node = AcquireNode(ino);
- if (node) {
- ReleaseNode(node);
- return 0
- }
+int MountMem::Unlink(const Path& path) {
+ AutoLock lock(&lock_);
+ MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
- errno = BADF;
- return -1;
-}
+ if (NULL == parent) return -1;
-int MountMem::Getdents(int ino, off_t offset, struct dirent *dirp, unsigned int count) {
- MountMemNode* node = AcquireNode(ino);
- if ((NULL == node) == 0) {
- errno = EBADF;
+ MountNode* child = parent->FindChild(path.Filename());
+ if (NULL == child) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (child->IsaDir()) {
+ errno = EISDIR;
return -1;
}
+ return parent->RemoveChild(path.Filename());
+}
+
+int MountMem::Mkdir(const Path& path, int mode) {
+ AutoLock lock(&lock_);
- if ((node->stat_.st_mode & S_IFDIR) == 0) {
- errno =ENOTDIR;
+ // We expect a Mount "absolute" path
+ if (!path.IsAbsolute()) {
+ errno = ENOENT;
return -1;
}
- if (offset + count > node->Size()) {
- count = node->Size() - offset;
+ // The root of the mount is already created by the mount
+ if (path.Size() == 1) {
+ errno = EEXIST;
+ return -1;
}
- memcpy(dirp, &node->data_[offset], count);
- return count;
-}
+ MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
+ MountNode* node;
-ssize_t MountMem::Write(int ino, off_t offset, const void *buf, size_t count) {
- MountMemNode* node = AcquireNode(ino);
+ // If we failed to find the parent, the error code is already set.
+ if (NULL == parent) return -1;
- if (NULL == node || (node->stat_.st_mode & S_IWUSER) == 0) {
- errno = EBADF;
+ node = parent->FindChild(path.Filename());
+ if (NULL != node) {
+ errno = EEXIST;
return -1;
}
- if (offset + count > node->Size()) {
- int err = node->Resize();
- if (err) {
- errno = err;
- ReleaseNode(node);
- return -1;
- }
+ // Otherwise, create a new node and attempt to add it
+ mode = OpenModeToPermission(mode);
+
+ // Allocate a node, with a RefCount of 1. If added to the parent
+ // it will get ref counted again. In either case, release the
+ // recount we have on exit.
+ node = AllocatePath(_S_IREAD | _S_IWRITE);
+ if (NULL == node) return -1;
+
+ if (parent->AddChild(path.Filename(), node) == -1) {
+ node->Release();
+ return -1;
}
- mempcy(&node->data_[offset], buf, count);
- ReleaseNode(node);
- return count;
+ node->Release();
+ return 0;
}
-ssize_t MountMem::Read(int ino, off_t offset, const void *buf, size_t count) {
- MountMemNode* node = AcquireNode(ino);
+int MountMem::Rmdir(const Path& path) {
+ AutoLock lock(&lock_);
- if (NULL == node || (node->stat_.st_mode & S_IRUSER) == 0) {
- errno = EBADF;
+ // We expect a Mount "absolute" path
+ if (!path.IsAbsolute()) {
+ errno = ENOENT;
return -1;
}
- if (offset + count > node->Size()) {
- count = node->Size() - offset;
+ // The root of the mount is already created by the mount
+ if (path.Size() == 1) {
+ errno = EEXIST;
+ return -1;
}
- mempcy(buf, &node->data_[offset], count);
- ReleaseNode(node);
- return count;
-}
+ MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
+ MountNode* node;
-int MountMem::Isatty(int ino) {
- // Acquire the node in case he node array is in flux
- MountMemNode* node = AcquireNode(ino);
+ // If we failed to find the parent, the error code is already set.
+ if (NULL == parent) return -1;
- if (node) {
- errno = ENOTTY;
- ReleaseNode(node);
+ // Verify we find a child which is also a directory
+ node = parent->FindChild(path.Filename());
+ if (NULL == node) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (!node->IsaDir()) {
+ errno = ENOTDIR;
+ return -1;
}
- else {
- errno = BADF;
+ if (node->ChildCount() > 0) {
+ errno = ENOTEMPTY;
+ return -1;
}
- return 0;
+ return parent->RemoveChild(path.Filename());
}
-
View
67 native_client_sdk/src/libraries/nacl_mounts/mount_mem.h
@@ -9,56 +9,45 @@
#include <map>
#include <string>
-#include "mount.h"
-#include "util/macros.h"
-#include "util/SlotAllocator.h"
+#include "nacl_mounts/mount.h"
-struct dirent;
-struct stat;
-class MountMemNode;
-
-// Mount serves as the base mounting class that will be used by
-// the mount manager (class MountManager). The mount manager
-// relies heavily on the GetNode method as a way of directing
-// system calls that take a path as an argument. The methods
-// of this class are pure virtual. BaseMount class contains
-// stub implementations for these methods. Feel free to use
-// BaseMount if your mount does not implement all of these
-// operations.
-class MountMem : public Mount {
+class MountMem : public MountFactory<MountMem, Mount> {
protected:
MountMem();
- virtual ~MountMem();
- // Init must be called by the factory before
- void Init();
+ virtual bool Init(int dev, StringMap_t& args);
+ virtual void Destroy();
- int MountMem::AddDirEntry(MountNode* node, MountNode* node, const char *name);
+ // The protected functions are only used internally and will not
+ // acquire or release the mount's lock themselves. The caller is
+ // returned to use correct locking as needed.
+ virtual MountNode *AllocateData(int mode);
+ virtual MountNode *AllocatePath(int mode);
+ virtual void ReleaseNode(MountNode *node);
- public:
- // System calls that can be overridden by a mount implementation
- virtual int Creat(const std::string& path, int mode, struct stat *st);
- virtual int Mkdir(const std::string& path, int mode, struct stat *st);
- virtual int Unlink(const std::string& path);
+ // Allocate or free an INODE number.
+ int AllocateINO();
+ void FreeINO(int ino);
- virtual int Rmdir(int node);
- virtual int Chmod(int node, int mode);
- virtual int Stat(int node, struct stat *buf);
- virtual int Fsync(int node);
+ // Find a Node specified node optionally failing if type does not match.
+ virtual MountNode* FindNode(const Path& path, int type = 0);
+
+ public:
+ typedef std::vector<ino_t> INOList_t;
- virtual int Getdents(int node, off_t offset, struct dirent *dirp,
- unsigned int count);
+ virtual MountNode *Open(const Path& path, int mode);
+ virtual int Close(MountNode* node);
+ virtual int Unlink(const Path& path);
+ virtual int Mkdir(const Path& path, int perm);
+ virtual int Rmdir(const Path& path);
- virtual ssize_t Read(int node, off_t offset,
- void *buf, size_t count);
- virtual ssize_t Write(int node, off_t offset,
- const void *buf, size_t count);
- virtual int Isatty(int node);
+private:
+ MountNode* root_;
+ INOList_t inos_;
+ size_t max_ino_;
- private:
- pthread_mutex_t lock_;
- SlotAllocator<MountMemNode> inodes_;
+ template <class M, class P> friend class MountFactory;
DISALLOW_COPY_AND_ASSIGN(MountMem);
};
View
15 native_client_sdk/src/libraries/nacl_mounts/mount_node.cc
@@ -13,8 +13,8 @@
#include "mount.h"
#include "mount_node.h"
-MountNode::MountNode(Mount* mount, int ino, int dev) :
- mount_(mount) {
+MountNode::MountNode(Mount* mount, int ino, int dev)
+ : mount_(mount) {
memset(&stat_, 0, sizeof(stat_));
stat_.st_ino = ino;
stat_.st_dev = dev;
@@ -23,16 +23,16 @@ MountNode::MountNode(Mount* mount, int ino, int dev) :
MountNode::~MountNode() {
}
-bool MountNode::Init(int mode, short gid, short uid) {
+bool MountNode::Init(int mode, short uid, short gid) {
stat_.st_mode = mode;
stat_.st_gid = gid;
stat_.st_uid = uid;
return true;
}
-void MountNode::Destroy() {
+int MountNode::Close() {
FSync();
- mount_->FreeNode(this);
+ return 0;
}
int MountNode::FSync() {
@@ -113,6 +113,11 @@ MountNode* MountNode::FindChild(const std::string& name) {
return NULL;
}
+int MountNode::ChildCount() {
+ errno = ENOTDIR;
+ return -1;
+}
+
void MountNode::Link() {
Acquire();
stat_.st_nlink++;
View
6 native_client_sdk/src/libraries/nacl_mounts/mount_node.h
@@ -23,7 +23,7 @@ class MountNode : public RefObject {
protected:
MountNode(Mount* mount, int ino, int dev);
virtual bool Init(int mode, short uid, short gid);
- virtual void Destroy();
+ virtual int Close();
public:
// Normal OS operations on a node (file), can be called by the kernel
@@ -55,6 +55,7 @@ class MountNode : public RefObject {
// Find a child and return it without updating the refcount
virtual MountNode* FindChild(const std::string& name);
+ virtual int ChildCount();
// Update the link count
virtual void Link();
@@ -64,7 +65,8 @@ class MountNode : public RefObject {
struct stat stat_;
Mount* mount_;
- friend class Mount;
+ friend class MountHFS;
+ friend class MountMem;
friend class MountNodeDir;
};
View
14 native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.cc
@@ -3,15 +3,17 @@
* found in the LICENSE file.
*/
+#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
+#include "macros.h"
#include "auto_lock.h"
#include "mount_node_dir.h"
-MountNodeDir::MountNodeDir(Mount* mount, int ino, int dev) :
- MountNode(mount, ino, dev),
- cache_(NULL) {
+MountNodeDir::MountNodeDir(Mount* mount, int ino, int dev)
+ : MountNode(mount, ino, dev),
+ cache_(NULL) {
}
MountNodeDir::~MountNodeDir() {
@@ -73,7 +75,6 @@ int MountNodeDir:: AddChild(const std::string& name, MountNode* node) {
errno = ENOENT;
return -1;
}
-
if (name.length() >= MEMBER_SIZE(struct dirent, d_name)) {
errno = ENAMETOOLONG;
return -1;
@@ -114,6 +115,11 @@ MountNode* MountNodeDir::FindChild(const std::string& name) {
return NULL;
}
+int MountNodeDir::ChildCount() {
+ AutoLock lock(&lock_);
+ return map_.size();
+}
+
void MountNodeDir::ClearCache() {
free(cache_);
cache_ = NULL;
View
8 native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.h
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-#include "mount_node.h"
+#include "nacl_mounts/mount_node.h"
class MountNodeDir : public MountNode {
@@ -32,7 +32,8 @@ class MountNodeDir : public MountNode {
// Adds a finds or adds a directory entry as an INO, updating the refcount
virtual int AddChild(const std::string& name, MountNode *node);
virtual int RemoveChild(const std::string& name);
- virtual MountNode* FindChild(const std::string& name);
+ virtual MountNode* FindChild(const std::string& name);
+ virtual int ChildCount();
protected:
@@ -42,7 +43,8 @@ class MountNodeDir : public MountNode {
private:
struct dirent* cache_;
MountNodeMap_t map_;
- friend class Mount;
+
+ friend class MountMem;
};
#endif // LIBRARIES_NACL_MOUNTS_MOUNT_NODE_DIR_H_
View
4 native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.h
@@ -6,7 +6,7 @@
#ifndef LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
#define LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
-#include "mount_node.h"
+#include "nacl_mounts/mount_node.h"
class MountNodeMem : public MountNode {
public:
@@ -25,7 +25,7 @@ class MountNodeMem : public MountNode {
private:
char* data_;
size_t capacity_;
- friend class Mount;
+ friend class MountMem;
};
#endif // LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
Please sign in to comment.
Something went wrong with that request. Please try again.