You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2012/05/31 01:42:03 UTC
svn commit: r1344507 - in /incubator/mesos/trunk/src: Makefile.am
linux/fs.cpp linux/fs.hpp tests/fs_tests.cpp
Author: benh
Date: Wed May 30 23:42:02 2012
New Revision: 1344507
URL: http://svn.apache.org/viewvc?rev=1344507&view=rev
Log:
Add utilities to monitor and control file systems on Linux (contributed by Jie Yu, https://reviews.apache.org/r/5186).
Added:
incubator/mesos/trunk/src/linux/fs.cpp
incubator/mesos/trunk/src/linux/fs.hpp
incubator/mesos/trunk/src/tests/fs_tests.cpp
Modified:
incubator/mesos/trunk/src/Makefile.am
Modified: incubator/mesos/trunk/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/Makefile.am?rev=1344507&r1=1344506&r2=1344507&view=diff
==============================================================================
--- incubator/mesos/trunk/src/Makefile.am (original)
+++ incubator/mesos/trunk/src/Makefile.am Wed May 30 23:42:02 2012
@@ -172,9 +172,11 @@ nodist_pkginclude_HEADERS = ../include/m
if OS_LINUX
libmesos_no_third_party_la_SOURCES += slave/lxc_isolation_module.cpp
+ libmesos_no_third_party_la_SOURCES += linux/fs.cpp
libmesos_no_third_party_la_SOURCES += linux/proc.cpp
else
EXTRA_DIST += slave/lxc_isolation_module.cpp
+ EXTRA_DIST += linux/fs.cpp
EXTRA_DIST += linux/proc.cpp
endif
@@ -193,10 +195,11 @@ libmesos_no_third_party_la_SOURCES += co
common/strings.hpp common/values.hpp \
configurator/configuration.hpp configurator/configurator.hpp \
configurator/option.hpp detector/detector.hpp \
- launcher/launcher.hpp linux/proc.hpp local/local.hpp \
- master/allocator.hpp master/allocator_factory.hpp \
- master/constants.hpp master/frameworks_manager.hpp \
- master/http.hpp master/master.hpp master/simple_allocator.hpp \
+ launcher/launcher.hpp linux/fs.hpp linux/proc.hpp \
+ local/local.hpp master/allocator.hpp \
+ master/allocator_factory.hpp master/constants.hpp \
+ master/frameworks_manager.hpp master/http.hpp \
+ master/master.hpp master/simple_allocator.hpp \
master/slaves_manager.hpp master/webui.hpp \
messages/messages.hpp slave/constants.hpp slave/http.hpp \
slave/isolation_module.hpp slave/isolation_module_factory.hpp \
@@ -759,6 +762,7 @@ mesos_tests_LDADD = ../third_party/libgm
mesos_tests_DEPENDENCIES = # Initialized to allow += below.
if OS_LINUX
+ mesos_tests_SOURCES += tests/fs_tests.cpp
mesos_tests_SOURCES += tests/proc_tests.cpp
endif
Added: incubator/mesos/trunk/src/linux/fs.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/linux/fs.cpp?rev=1344507&view=auto
==============================================================================
--- incubator/mesos/trunk/src/linux/fs.cpp (added)
+++ incubator/mesos/trunk/src/linux/fs.cpp Wed May 30 23:42:02 2012
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <linux/limits.h>
+
+#include "common/lock.hpp"
+
+#include "linux/fs.hpp"
+
+
+namespace mesos {
+namespace internal {
+namespace fs {
+
+
+// Lock for guarding accesses to fstab functions.
+static Lock* fstabLock = new Lock(new pthread_mutex_t);
+// Lock for guarding accesses to mntent functions.
+static Lock* mntentLock = new Lock(new pthread_mutex_t);
+
+
+bool MountTable::Entry::hasOption(const std::string& option)
+{
+ struct mntent mntent;
+ mntent.mnt_fsname = const_cast<char*>(fsname.c_str());
+ mntent.mnt_dir = const_cast<char*>(dir.c_str());
+ mntent.mnt_type = const_cast<char*>(type.c_str());
+ mntent.mnt_opts = const_cast<char*>(opts.c_str());
+ mntent.mnt_freq = freq;
+ mntent.mnt_passno = passno;
+ return ::hasmntopt(&mntent, option.c_str()) != NULL;
+}
+
+
+Try<MountTable> MountTable::read(const std::string& path)
+{
+ MountTable table;
+
+ FILE* file = ::setmntent(path.c_str(), "r");
+ if (file == NULL) {
+ return Try<MountTable>::error("Failed to open " + path);
+ }
+
+ while (true) {
+#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
+ // Reentrant version exists.
+ struct mntent mntentBuffer;
+ char strBuffer[PATH_MAX];
+ struct mntent* mntent = ::getmntent_r(file, &mntentBuffer, strBuffer,
+ sizeof(strBuffer));
+ if (mntent == NULL) {
+ // NULL means the end of enties.
+ break;
+ }
+
+ MountTable::Entry entry(mntent->mnt_fsname,
+ mntent->mnt_dir,
+ mntent->mnt_type,
+ mntent->mnt_opts,
+ mntent->mnt_freq,
+ mntent->mnt_passno);
+ table.entries.push_back(entry);
+#else
+ // Reentrant version does not exist. Use locks.
+ mntentLock->lock();
+ {
+ struct mntent* mntent = ::getmntent(file);
+ if (mntent == NULL) {
+ // NULL means the end of enties.
+ mntentLock->unlock();
+ break;
+ }
+
+ MountTable::Entry entry(mntent->mnt_fsname,
+ mntent->mnt_dir,
+ mntent->mnt_type,
+ mntent->mnt_opts,
+ mntent->mnt_freq,
+ mntent->mnt_passno);
+ table.entries.push_back(entry);
+ }
+ mntentLock->unlock();
+#endif
+ }
+
+ ::endmntent(file);
+
+ return table;
+}
+
+
+Try<FileSystemTable> FileSystemTable::read()
+{
+ FileSystemTable table;
+
+ // Use locks since fstab functions are not thread-safe.
+ fstabLock->lock();
+ {
+ // Open file _PATH_FSTAB (/etc/fstab).
+ if (::setfsent() == 0) {
+ fstabLock->unlock();
+ return Try<FileSystemTable>::error("Failed to open file system table");
+ }
+
+ while (true) {
+ struct fstab* fstab = ::getfsent();
+ if (fstab == NULL) {
+ // NULL means the end of enties.
+ break;
+ }
+
+ FileSystemTable::Entry entry(fstab->fs_spec,
+ fstab->fs_file,
+ fstab->fs_vfstype,
+ fstab->fs_mntops,
+ fstab->fs_type,
+ fstab->fs_freq,
+ fstab->fs_passno);
+ table.entries.push_back(entry);
+ }
+
+ ::endfsent();
+ }
+ fstabLock->unlock();
+
+ return table;
+}
+
+
+Try<bool> mount(const std::string& source,
+ const std::string& target,
+ const std::string& type,
+ unsigned long flags,
+ const void* data)
+{
+ // The prototype of function 'mount' on Linux is as follows:
+ // int mount(const char *source, const char *target,
+ // const char *filesystemtype, unsigned long mountflags,
+ // const void *data);
+ if (::mount(source.c_str(), target.c_str(), type.c_str(), flags, data) < 0) {
+ return Try<bool>::error(
+ "Failed to mount " + source + " at " + target + ": " + strerror(errno));
+ }
+
+ return true;
+}
+
+
+Try<bool> unmount(const std::string& target, int flags)
+{
+ // The prototype of function 'umount2' on Linux is as follows:
+ // int umount2(const char *target, int flags);
+ if (::umount2(target.c_str(), flags) < 0) {
+ return Try<bool>::error(
+ "Failed to unmount " + target + ": " + strerror(errno));
+ }
+
+ return true;
+}
+
+
+} // namespace fs {
+} // namespace internal {
+} // namespace mesos {
Added: incubator/mesos/trunk/src/linux/fs.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/linux/fs.hpp?rev=1344507&view=auto
==============================================================================
--- incubator/mesos/trunk/src/linux/fs.hpp (added)
+++ incubator/mesos/trunk/src/linux/fs.hpp Wed May 30 23:42:02 2012
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FS_HPP__
+#define __FS_HPP__
+
+#include <fstab.h>
+#include <mntent.h>
+
+#include <sys/mount.h>
+
+#include <string>
+#include <vector>
+
+#include "common/try.hpp"
+
+
+namespace mesos {
+namespace internal {
+namespace fs {
+
+
+// Structure describing a mount table (e.g. /etc/mtab or /proc/mounts).
+struct MountTable {
+ // Structure describing a mount table entry. This is a wrapper for struct
+ // mntent defined in <mntent.h>.
+ struct Entry {
+ Entry() : freq(0), passno(0) {}
+
+ Entry(const std::string& _fsname,
+ const std::string& _dir,
+ const std::string& _type,
+ const std::string& _opts,
+ int _freq,
+ int _passno)
+ : fsname(_fsname),
+ dir(_dir),
+ type(_type),
+ opts(_opts),
+ freq(_freq),
+ passno(_passno)
+ {}
+
+ // Check whether a given mount option exists in a mount table entry.
+ // @param option The given mount option.
+ // @return Whether the given mount option exists.
+ bool hasOption(const std::string& option);
+
+ std::string fsname; // Device or server for filesystem.
+ std::string dir; // Directory mounted on.
+ std::string type; // Type of filesystem: ufs, nfs, etc.
+ std::string opts; // Comma-separated options for fs.
+ int freq; // Dump frequency (in days).
+ int passno; // Pass number for `fsck'.
+ };
+
+ // Read the mount table from a file.
+ // @param path The path of the file storing the mount table.
+ // @return An instance of MountTable if success.
+ static Try<MountTable> read(const std::string& path);
+
+ std::vector<Entry> entries;
+};
+
+
+// Structure describing a file system table (e.g. /etc/fstab).
+struct FileSystemTable {
+ // Structure describing a file system table entry. This is a wrapper for
+ // struct fstab defined in <fstab.h>
+ struct Entry {
+ Entry() : freq(0), passno(0) {}
+
+ Entry(const std::string& _spec,
+ const std::string& _file,
+ const std::string& _vfstype,
+ const std::string& _mntops,
+ const std::string& _type,
+ int _freq,
+ int _passno)
+ : spec(_spec),
+ file(_file),
+ vfstype(_vfstype),
+ mntops(_mntops),
+ type(_type),
+ freq(_freq),
+ passno(_passno)
+ {}
+
+ std::string spec; // Block special device name.
+ std::string file; // File system path prefix.
+ std::string vfstype; // File system type, ufs, nfs.
+ std::string mntops; // Mount options ala -o.
+ std::string type; // FSTAB_* from fs_mntops.
+ int freq; // Dump frequency, in days.
+ int passno; // Pass number on parallel dump.
+ };
+
+ // Read the file system table from a file.
+ // @param path The path of the file storing the file system table.
+ // @return An instance of FileSystemTable if success.
+ static Try<FileSystemTable> read();
+
+ std::vector<Entry> entries;
+};
+
+
+// Mount a file system.
+// @param source Specify the file system (often a device name).
+// @param target Directory to be attached to.
+// @param type File system type (listed in /proc/filesystems).
+// @param flags Mount flags.
+// @param data Extra data interpreted by different file systems.
+// @return Whether the mount operation successes.
+Try<bool> mount(const std::string& source,
+ const std::string& target,
+ const std::string& type,
+ unsigned long flags,
+ const void* data);
+
+
+// Unmount a file system.
+// @param target The (topmost) directory where the file system attaches.
+// @param flags Unmount flags.
+// @return Whether the unmount operation successes.
+Try<bool> unmount(const std::string& target, int flags = 0);
+
+
+} // namespace fs {
+} // namespace internal {
+} // namespace mesos {
+
+
+#endif // __FS_HPP__
Added: incubator/mesos/trunk/src/tests/fs_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/fs_tests.cpp?rev=1344507&view=auto
==============================================================================
--- incubator/mesos/trunk/src/tests/fs_tests.cpp (added)
+++ incubator/mesos/trunk/src/tests/fs_tests.cpp Wed May 30 23:42:02 2012
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <paths.h>
+
+#include <gmock/gmock.h>
+
+#include "common/option.hpp"
+#include "common/try.hpp"
+
+#include "common/foreach.hpp"
+#include "linux/fs.hpp"
+
+using namespace mesos;
+using namespace mesos::internal;
+
+using fs::MountTable;
+using fs::FileSystemTable;
+
+
+TEST(FsTest, MountTableRead)
+{
+ Try<MountTable> table = MountTable::read(_PATH_MOUNTED);
+
+ ASSERT_TRUE(table.isSome());
+
+ Option<MountTable::Entry> root = Option<MountTable::Entry>::none();
+ Option<MountTable::Entry> proc = Option<MountTable::Entry>::none();
+ foreach (const MountTable::Entry& entry, table.get().entries) {
+ if (entry.dir == "/") {
+ root = entry;
+ } else if (entry.dir == "/proc") {
+ proc = entry;
+ }
+ }
+
+ EXPECT_TRUE(root.isSome());
+ ASSERT_TRUE(proc.isSome());
+ EXPECT_EQ(proc.get().type, "proc");
+}
+
+
+TEST(FsTest, MountTableHasOption)
+{
+ Try<MountTable> table = MountTable::read(_PATH_MOUNTED);
+
+ ASSERT_TRUE(table.isSome());
+
+ Option<MountTable::Entry> proc = Option<MountTable::Entry>::none();
+ foreach (const MountTable::Entry& entry, table.get().entries) {
+ if (entry.dir == "/proc") {
+ proc = entry;
+ }
+ }
+
+ ASSERT_TRUE(proc.isSome());
+ EXPECT_TRUE(proc.get().hasOption("rw"));
+ EXPECT_TRUE(proc.get().hasOption("noexec"));
+ EXPECT_TRUE(proc.get().hasOption("nodev"));
+}
+
+
+TEST(FsTest, FileSystemTableRead)
+{
+ Try<FileSystemTable> table = FileSystemTable::read();
+
+ ASSERT_TRUE(table.isSome());
+
+ Option<FileSystemTable::Entry> root = Option<FileSystemTable::Entry>::none();
+ Option<FileSystemTable::Entry> proc = Option<FileSystemTable::Entry>::none();
+ foreach (const FileSystemTable::Entry& entry, table.get().entries) {
+ if (entry.file == "/") {
+ root = entry;
+ } else if (entry.file == "/proc") {
+ proc = entry;
+ }
+ }
+
+ EXPECT_TRUE(root.isSome());
+ ASSERT_TRUE(proc.isSome());
+ EXPECT_EQ(proc.get().vfstype, "proc");
+}