Add f2fs support for private volumes.
When formatting volumes, pass along fsType string which can be "auto"
to let the volume select the best choice. For now, private volumes
assume that MMC devices (like SD cards) are best off using f2fs when
both kernel support and tools are present, otherwise fall back to
ext4. Use blkid when mounting to pick the right set of tools.
Move filesystem utility methods into namespaces and place in separate
directory to be more organized.
Bug: 20275581
Change-Id: Id5f82d8672dda2e9f68c35b075f28232b0b55ed4
diff --git a/PrivateVolume.cpp b/PrivateVolume.cpp
index ff2c7b3..a1bbb3b 100644
--- a/PrivateVolume.cpp
+++ b/PrivateVolume.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include "Ext4.h"
+#include "fs/Ext4.h"
+#include "fs/F2fs.h"
#include "PrivateVolume.h"
#include "EmulatedVolume.h"
#include "Utils.h"
@@ -40,6 +41,8 @@
namespace android {
namespace vold {
+static const unsigned int kMajorBlockMmc = 179;
+
PrivateVolume::PrivateVolume(dev_t device, const std::string& keyRaw) :
VolumeBase(Type::kPrivate), mRawDevice(device), mKeyRaw(keyRaw) {
setId(StringPrintf("private:%u,%u", major(device), minor(device)));
@@ -101,16 +104,36 @@
return -EIO;
}
- int res = Ext4::check(mDmDevPath.c_str(), mPath.c_str());
- if (res == 0 || res == 1) {
- LOG(DEBUG) << getId() << " passed filesystem check";
- } else {
- PLOG(ERROR) << getId() << " failed filesystem check";
- return -EIO;
- }
+ if (mFsType == "ext4") {
+ int res = ext4::Check(mDmDevPath, mPath);
+ if (res == 0 || res == 1) {
+ LOG(DEBUG) << getId() << " passed filesystem check";
+ } else {
+ PLOG(ERROR) << getId() << " failed filesystem check";
+ return -EIO;
+ }
- if (Ext4::doMount(mDmDevPath.c_str(), mPath.c_str(), false, false, true)) {
- PLOG(ERROR) << getId() << " failed to mount";
+ if (ext4::Mount(mDmDevPath, mPath, false, false, true)) {
+ PLOG(ERROR) << getId() << " failed to mount";
+ return -EIO;
+ }
+
+ } else if (mFsType == "f2fs") {
+ int res = f2fs::Check(mDmDevPath);
+ if (res == 0) {
+ LOG(DEBUG) << getId() << " passed filesystem check";
+ } else {
+ PLOG(ERROR) << getId() << " failed filesystem check";
+ return -EIO;
+ }
+
+ if (f2fs::Mount(mDmDevPath, mPath)) {
+ PLOG(ERROR) << getId() << " failed to mount";
+ return -EIO;
+ }
+
+ } else {
+ LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
return -EIO;
}
@@ -124,6 +147,8 @@
return -EIO;
}
+ // TODO: restorecon all the things!
+
// Create a new emulated volume stacked above us, it will automatically
// be destroyed during unmount
std::string mediaPath(mPath + "/media");
@@ -145,11 +170,33 @@
return OK;
}
-status_t PrivateVolume::doFormat() {
- // TODO: change mountpoint once we have selinux labels
- if (Ext4::format(mDmDevPath.c_str(), 0, "/data")) {
- PLOG(ERROR) << getId() << " failed to format";
- return -EIO;
+status_t PrivateVolume::doFormat(const std::string& fsType) {
+ std::string resolvedFsType = fsType;
+ if (fsType == "auto") {
+ // For now, assume that all MMC devices are flash-based SD cards, and
+ // give everyone else ext4 because sysfs rotational isn't reliable.
+ if ((major(mRawDevice) == kMajorBlockMmc) && f2fs::IsSupported()) {
+ resolvedFsType = "f2fs";
+ } else {
+ resolvedFsType = "ext4";
+ }
+ LOG(DEBUG) << "Resolved auto to " << resolvedFsType;
+ }
+
+ if (resolvedFsType == "ext4") {
+ // TODO: change reported mountpoint once we have better selinux support
+ if (ext4::Format(mDmDevPath, 0, "/data")) {
+ PLOG(ERROR) << getId() << " failed to format";
+ return -EIO;
+ }
+ } else if (resolvedFsType == "f2fs") {
+ if (f2fs::Format(mDmDevPath)) {
+ PLOG(ERROR) << getId() << " failed to format";
+ return -EIO;
+ }
+ } else {
+ LOG(ERROR) << getId() << " unsupported filesystem " << fsType;
+ return -EINVAL;
}
return OK;