am d0640f63: Add f2fs support for private volumes.

* commit 'd0640f6358041f7e2657167560b357078db73526':
  Add f2fs support for private volumes.
gugelfrei
Jeff Sharkey 9 years ago committed by Android Git Automerger
commit d6a77b518c

@ -8,8 +8,9 @@ common_src_files := \
NetlinkManager.cpp \
NetlinkHandler.cpp \
Process.cpp \
Ext4.cpp \
Fat.cpp \
fs/Ext4.cpp \
fs/F2fs.cpp \
fs/Vfat.cpp \
Loop.cpp \
Devmapper.cpp \
ResponseCode.cpp \

@ -223,15 +223,16 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
return sendGenericOkFail(cli, vol->unmount());
} else if (cmd == "format" && argc > 2) {
// format [volId]
} else if (cmd == "format" && argc > 3) {
// format [volId] [fsType|auto]
std::string id(argv[2]);
std::string fsType(argv[3]);
auto vol = vm->findVolume(id);
if (vol == nullptr) {
return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
}
return sendGenericOkFail(cli, vol->format());
return sendGenericOkFail(cli, vol->format(fsType));
} else if (cmd == "move_storage" && argc > 3) {
// move_storage [fromVolId] [toVolId]

@ -136,7 +136,7 @@ void Disk::createPublicVolume(dev_t device) {
LOG(DEBUG) << "Device just partitioned; silently formatting";
vol->setSilent(true);
vol->create();
vol->format();
vol->format("auto");
vol->destroy();
vol->setSilent(false);
}
@ -168,7 +168,7 @@ void Disk::createPrivateVolume(dev_t device, const std::string& partGuid) {
LOG(DEBUG) << "Device just partitioned; silently formatting";
vol->setSilent(true);
vol->create();
vol->format();
vol->format("auto");
vol->destroy();
vol->setSilent(false);
}

@ -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 @@ using android::base::StringPrintf;
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 @@ status_t PrivateVolume::doMount() {
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::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;
}
if (Ext4::doMount(mDmDevPath.c_str(), mPath.c_str(), false, false, true)) {
PLOG(ERROR) << getId() << " failed to mount";
} else {
LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
return -EIO;
}
@ -124,6 +147,8 @@ status_t PrivateVolume::doMount() {
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 @@ status_t PrivateVolume::doUnmount() {
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;

@ -45,7 +45,7 @@ protected:
status_t doDestroy() override;
status_t doMount() override;
status_t doUnmount() override;
status_t doFormat() override;
status_t doFormat(const std::string& fsType) override;
status_t readMetadata();

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "Fat.h"
#include "fs/Vfat.h"
#include "PublicVolume.h"
#include "Utils.h"
#include "VolumeManager.h"
@ -94,7 +94,7 @@ status_t PublicVolume::doMount() {
// TODO: expand to support mounting other filesystems
readMetadata();
if (Fat::check(mDevPath.c_str())) {
if (vfat::Check(mDevPath)) {
LOG(ERROR) << getId() << " failed filesystem check";
return -EIO;
}
@ -119,7 +119,7 @@ status_t PublicVolume::doMount() {
return -errno;
}
if (Fat::doMount(mDevPath.c_str(), mRawPath.c_str(), false, false, false,
if (vfat::Mount(mDevPath, mRawPath, false, false, false,
AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
return -EIO;
@ -200,11 +200,20 @@ status_t PublicVolume::doUnmount() {
return OK;
}
status_t PublicVolume::doFormat() {
if (Fat::format(mDevPath.c_str(), 0, true)) {
LOG(ERROR) << getId() << " failed to format";
return -errno;
status_t PublicVolume::doFormat(const std::string& fsType) {
if (fsType == "vfat" || fsType == "auto") {
if (WipeBlockDevice(mDevPath) != OK) {
LOG(WARNING) << getId() << " failed to wipe";
}
if (vfat::Format(mDevPath, 0)) {
LOG(ERROR) << getId() << " failed to format";
return -errno;
}
} else {
LOG(ERROR) << "Unsupported filesystem " << fsType;
return -EINVAL;
}
return OK;
}

@ -47,7 +47,7 @@ protected:
status_t doDestroy() override;
status_t doMount() override;
status_t doUnmount() override;
status_t doFormat() override;
status_t doFormat(const std::string& fsType) override;
status_t readMetadata();
status_t initAsecStage();

@ -18,6 +18,7 @@
#include "Utils.h"
#include "Process.h"
#include <base/file.h>
#include <base/logging.h>
#include <base/stringprintf.h>
#include <cutils/fs.h>
@ -39,6 +40,7 @@
#define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
#endif
using android::base::ReadFileToString;
using android::base::StringPrintf;
namespace android {
@ -51,6 +53,8 @@ security_context_t sFsckUntrustedContext = nullptr;
static const char* kBlkidPath = "/system/bin/blkid";
static const char* kProcFilesystems = "/proc/filesystems";
status_t CreateDeviceNode(const std::string& path, dev_t dev) {
const char* cpath = path.c_str();
status_t res = 0;
@ -463,5 +467,47 @@ uint64_t GetTreeBytes(const std::string& path) {
}
}
bool IsFilesystemSupported(const std::string& fsType) {
std::string supported;
if (!ReadFileToString(kProcFilesystems, &supported)) {
PLOG(ERROR) << "Failed to read supported filesystems";
return false;
}
return supported.find(fsType + "\n") != std::string::npos;
}
status_t WipeBlockDevice(const std::string& path) {
status_t res = -1;
const char* c_path = path.c_str();
unsigned long nr_sec = 0;
unsigned long long range[2];
int fd = TEMP_FAILURE_RETRY(open(c_path, O_RDWR | O_CLOEXEC));
if (fd == -1) {
PLOG(ERROR) << "Failed to open " << path;
goto done;
}
if ((ioctl(fd, BLKGETSIZE, nr_sec)) == -1) {
PLOG(ERROR) << "Failed to determine size of " << path;
goto done;
}
range[0] = 0;
range[1] = (unsigned long long) nr_sec * 512;
LOG(INFO) << "About to discard " << range[1] << " on " << path;
if (ioctl(fd, BLKDISCARD, &range) == 0) {
LOG(INFO) << "Discard success on " << path;
res = 0;
} else {
PLOG(ERROR) << "Discard failure on " << path;
}
done:
close(fd);
return res;
}
} // namespace vold
} // namespace android

@ -81,6 +81,11 @@ status_t StrToHex(const std::string& str, std::string& hex);
uint64_t GetFreeBytes(const std::string& path);
uint64_t GetTreeBytes(const std::string& path);
bool IsFilesystemSupported(const std::string& fsType);
/* Wipes contents of block device at given path */
status_t WipeBlockDevice(const std::string& path);
} // namespace vold
} // namespace android

@ -222,7 +222,7 @@ status_t VolumeBase::unmount() {
return res;
}
status_t VolumeBase::format() {
status_t VolumeBase::format(const std::string& fsType) {
if (mState == State::kMounted) {
unmount();
}
@ -233,12 +233,12 @@ status_t VolumeBase::format() {
}
setState(State::kFormatting);
status_t res = doFormat();
status_t res = doFormat(fsType);
setState(State::kUnmounted);
return res;
}
status_t VolumeBase::doFormat() {
status_t VolumeBase::doFormat(const std::string& fsType) {
return -ENOTSUP;
}

@ -97,7 +97,7 @@ public:
status_t destroy();
status_t mount();
status_t unmount();
status_t format();
status_t format(const std::string& fsType);
protected:
explicit VolumeBase(Type type);
@ -106,7 +106,7 @@ protected:
virtual status_t doDestroy();
virtual status_t doMount() = 0;
virtual status_t doUnmount() = 0;
virtual status_t doFormat();
virtual status_t doFormat(const std::string& fsType);
status_t setId(const std::string& id);
status_t setPath(const std::string& path);

@ -51,8 +51,8 @@
#include "NetlinkManager.h"
#include "ResponseCode.h"
#include "Loop.h"
#include "Ext4.h"
#include "Fat.h"
#include "fs/Ext4.h"
#include "fs/Vfat.h"
#include "Utils.h"
#include "Devmapper.h"
#include "Process.h"
@ -725,9 +725,9 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
}
if (usingExt4) {
formatStatus = Ext4::format(dmDevice, numImgSectors, mountPoint);
formatStatus = android::vold::ext4::Format(dmDevice, numImgSectors, mountPoint);
} else {
formatStatus = Fat::format(dmDevice, numImgSectors, 0);
formatStatus = android::vold::vfat::Format(dmDevice, numImgSectors);
}
if (formatStatus < 0) {
@ -754,10 +754,11 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
int mountStatus;
if (usingExt4) {
mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false);
mountStatus = android::vold::ext4::Mount(dmDevice, mountPoint,
false, false, false);
} else {
mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000,
false);
mountStatus = android::vold::vfat::Mount(dmDevice, mountPoint,
false, false, false, ownerUid, 0, 0000, false);
}
if (mountStatus) {
@ -916,7 +917,7 @@ int VolumeManager::resizeAsec(const char *id, unsigned numSectors, const char *k
*/
waitForDevMapper(dmDevice);
if (Ext4::resize(dmDevice, numImgSectors)) {
if (android::vold::ext4::Resize(dmDevice, numImgSectors)) {
SLOGE("Unable to resize %s (%s)", id, strerror(errno));
if (cleanupDm) {
Devmapper::destroy(idHash);
@ -973,9 +974,11 @@ int VolumeManager::finalizeAsec(const char *id) {
int result = 0;
if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
result = Ext4::doMount(loopDevice, mountPoint, true, true, true);
result = android::vold::ext4::Mount(loopDevice, mountPoint,
true, true, true);
} else {
result = Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false);
result = android::vold::vfat::Mount(loopDevice, mountPoint,
true, true, true, 0, 0, 0227, false);
}
if (result) {
@ -1039,7 +1042,7 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f
return 0;
}
int ret = Ext4::doMount(loopDevice, mountPoint,
int ret = android::vold::ext4::Mount(loopDevice, mountPoint,
false /* read-only */,
true /* remount */,
false /* executable */);
@ -1101,7 +1104,7 @@ int VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* f
result |= -1;
}
result |= Ext4::doMount(loopDevice, mountPoint,
result |= android::vold::ext4::Mount(loopDevice, mountPoint,
true /* read-only */,
true /* remount */,
true /* execute */);
@ -1537,9 +1540,11 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid, bool
int result;
if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
result = Ext4::doMount(dmDevice, mountPoint, readOnly, false, readOnly);
result = android::vold::ext4::Mount(dmDevice, mountPoint,
readOnly, false, readOnly);
} else {
result = Fat::doMount(dmDevice, mountPoint, readOnly, false, readOnly, ownerUid, 0, 0222, false);
result = android::vold::vfat::Mount(dmDevice, mountPoint,
readOnly, false, readOnly, ownerUid, 0, 0222, false);
}
if (result) {
@ -1628,8 +1633,8 @@ int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
*/
waitForDevMapper(dmDevice);
if (Fat::doMount(dmDevice, mountPoint, true, false, true, 0, ownerGid,
0227, false)) {
if (android::vold::vfat::Mount(dmDevice, mountPoint,
true, false, true, 0, ownerGid, 0227, false)) {
SLOGE("Image mount failed (%s)", strerror(errno));
if (cleanupDm) {
Devmapper::destroy(idHash);

@ -50,16 +50,26 @@
using android::base::StringPrintf;
namespace android {
namespace vold {
namespace ext4 {
static const char* kResizefsPath = "/system/bin/resize2fs";
static const char* kMkfsPath = "/system/bin/make_ext4fs";
static const char* kFsckPath = "/system/bin/e2fsck";
int Ext4::check(const char *fsPath, const char *mountPoint) {
bool IsSupported() {
return access(kMkfsPath, X_OK) == 0
&& access(kFsckPath, X_OK) == 0
&& IsFilesystemSupported("ext4");
}
status_t Check(const std::string& source, const std::string& target) {
// The following is shamelessly borrowed from fs_mgr.c, so it should be
// kept in sync with any changes over there.
char* blk_device = (char*) fsPath;
char* target = (char*) mountPoint;
const char* c_source = source.c_str();
const char* c_target = target.c_str();
int status;
int ret;
@ -79,17 +89,17 @@ int Ext4::check(const char *fsPath, const char *mountPoint) {
* filesytsem due to an error, e2fsck is still run to do a full check
* fix the filesystem.
*/
ret = mount(blk_device, target, "ext4", tmpmnt_flags, tmpmnt_opts);
ret = mount(c_source, c_target, "ext4", tmpmnt_flags, tmpmnt_opts);
if (!ret) {
int i;
for (i = 0; i < 5; i++) {
// Try to umount 5 times before continuing on.
// Should we try rebooting if all attempts fail?
int result = umount(target);
int result = umount(c_target);
if (result == 0) {
break;
}
ALOGW("%s(): umount(%s)=%d: %s\n", __func__, target, result, strerror(errno));
ALOGW("%s(): umount(%s)=%d: %s\n", __func__, c_target, result, strerror(errno));
sleep(1);
}
}
@ -100,61 +110,65 @@ int Ext4::check(const char *fsPath, const char *mountPoint) {
*/
if (access(kFsckPath, X_OK)) {
ALOGD("Not running %s on %s (executable not in system image)\n",
kFsckPath, blk_device);
kFsckPath, c_source);
} else {
ALOGD("Running %s on %s\n", kFsckPath, blk_device);
ALOGD("Running %s on %s\n", kFsckPath, c_source);
std::vector<std::string> cmd;
cmd.push_back(kFsckPath);
cmd.push_back("-y");
cmd.push_back(blk_device);
cmd.push_back(c_source);
// Ext4 devices are currently always trusted
return android::vold::ForkExecvp(cmd, android::vold::sFsckContext);
// ext4 devices are currently always trusted
return ForkExecvp(cmd, sFsckContext);
}
return 0;
}
int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
bool executable) {
status_t Mount(const std::string& source, const std::string& target, bool ro,
bool remount, bool executable) {
int rc;
unsigned long flags;
const char* c_source = source.c_str();
const char* c_target = target.c_str();
flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
flags |= (executable ? 0 : MS_NOEXEC);
flags |= (ro ? MS_RDONLY : 0);
flags |= (remount ? MS_REMOUNT : 0);
rc = mount(fsPath, mountPoint, "ext4", flags, NULL);
rc = mount(c_source, c_target, "ext4", flags, NULL);
if (rc && errno == EROFS) {
SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
flags |= MS_RDONLY;
rc = mount(fsPath, mountPoint, "ext4", flags, NULL);
rc = mount(c_source, c_target, "ext4", flags, NULL);
}
return rc;
}
int Ext4::resize(const char *fspath, unsigned int numSectors) {
status_t Resize(const std::string& source, unsigned int numSectors) {
std::vector<std::string> cmd;
cmd.push_back(kResizefsPath);
cmd.push_back("-f");
cmd.push_back(fspath);
cmd.push_back(source);
cmd.push_back(StringPrintf("%u", numSectors));
return android::vold::ForkExecvp(cmd);
return ForkExecvp(cmd);
}
int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) {
status_t Format(const std::string& source, unsigned int numSectors,
const std::string& target) {
std::vector<std::string> cmd;
cmd.push_back(kMkfsPath);
cmd.push_back("-J");
cmd.push_back("-a");
cmd.push_back(mountpoint);
cmd.push_back(target);
if (numSectors) {
cmd.push_back("-l");
@ -163,7 +177,11 @@ int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountp
// Always generate a real UUID
cmd.push_back("-u");
cmd.push_back(fsPath);
cmd.push_back(source);
return android::vold::ForkExecvp(cmd);
return ForkExecvp(cmd);
}
} // namespace ext4
} // namespace vold
} // namespace android

@ -0,0 +1,41 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed 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 ANDROID_VOLD_EXT4_H
#define ANDROID_VOLD_EXT4_H
#include <utils/Errors.h>
#include <string>
namespace android {
namespace vold {
namespace ext4 {
bool IsSupported();
status_t Check(const std::string& source, const std::string& target);
status_t Mount(const std::string& source, const std::string& target, bool ro,
bool remount, bool executable);
status_t Format(const std::string& source, unsigned int numSectors,
const std::string& target);
status_t Resize(const std::string& source, unsigned int numSectors);
} // namespace ext4
} // namespace vold
} // namespace android
#endif

@ -0,0 +1,82 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed 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 "F2fs.h"
#include "Utils.h"
#include <base/logging.h>
#include <base/stringprintf.h>
#include <vector>
#include <string>
#include <sys/mount.h>
using android::base::StringPrintf;
namespace android {
namespace vold {
namespace f2fs {
static const char* kMkfsPath = "/system/bin/make_f2fs";
static const char* kFsckPath = "/system/bin/fsck.f2fs";
bool IsSupported() {
return access(kMkfsPath, X_OK) == 0
&& access(kFsckPath, X_OK) == 0
&& IsFilesystemSupported("f2fs");
}
status_t Check(const std::string& source) {
std::vector<std::string> cmd;
cmd.push_back(kFsckPath);
cmd.push_back("-f");
cmd.push_back(source);
// f2fs devices are currently always trusted
return ForkExecvp(cmd, sFsckContext);
}
status_t Mount(const std::string& source, const std::string& target) {
const char* c_source = source.c_str();
const char* c_target = target.c_str();
unsigned long flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
int res = mount(c_source, c_target, "f2fs", flags, NULL);
if (res != 0) {
PLOG(ERROR) << "Failed to mount " << source;
if (errno == EROFS) {
res = mount(c_source, c_target, "f2fs", flags | MS_RDONLY, NULL);
if (res != 0) {
PLOG(ERROR) << "Failed to mount read-only " << source;
}
}
}
return res;
}
status_t Format(const std::string& source) {
std::vector<std::string> cmd;
cmd.push_back(kMkfsPath);
cmd.push_back(source);
return ForkExecvp(cmd);
}
} // namespace f2fs
} // namespace vold
} // namespace android

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012 The Android Open Source Project
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,18 +14,25 @@
* limitations under the License.
*/
#ifndef _EXT4_H
#define _EXT4_H
#ifndef ANDROID_VOLD_F2FS_H
#define ANDROID_VOLD_F2FS_H
#include <unistd.h>
#include <utils/Errors.h>
class Ext4 {
public:
static int check(const char *fsPath, const char *mountPoint);
static int doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
bool executable);
static int format(const char *fsPath, unsigned int numSectors, const char *mountpoint);
static int resize(const char *fsPath, unsigned int numSectors);
};
#include <string>
namespace android {
namespace vold {
namespace f2fs {
bool IsSupported();
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target);
status_t Format(const std::string& source);
} // namespace f2fs
} // namespace vold
} // namespace android
#endif

@ -45,16 +45,26 @@
#include <logwrap/logwrap.h>
#include "Fat.h"
#include "Vfat.h"
#include "Utils.h"
#include "VoldUtil.h"
using android::base::StringPrintf;
namespace android {
namespace vold {
namespace vfat {
static const char* kMkfsPath = "/system/bin/newfs_msdos";
static const char* kFsckPath = "/system/bin/fsck_msdos";
int Fat::check(const char *fsPath) {
bool IsSupported() {
return access(kMkfsPath, X_OK) == 0
&& access(kFsckPath, X_OK) == 0
&& IsFilesystemSupported("vfat");
}
status_t Check(const std::string& source) {
if (access(kFsckPath, X_OK)) {
SLOGW("Skipping fs checks\n");
return 0;
@ -67,10 +77,10 @@ int Fat::check(const char *fsPath) {
cmd.push_back(kFsckPath);
cmd.push_back("-p");
cmd.push_back("-f");
cmd.push_back(fsPath);
cmd.push_back(source);
// Fat devices are currently always untrusted
rc = android::vold::ForkExecvp(cmd, android::vold::sFsckUntrustedContext);
rc = ForkExecvp(cmd, sFsckUntrustedContext);
if (rc < 0) {
SLOGE("Filesystem check failed due to logwrap error");
@ -108,13 +118,16 @@ int Fat::check(const char *fsPath) {
return 0;
}
int Fat::doMount(const char *fsPath, const char *mountPoint,
bool ro, bool remount, bool executable,
int ownerUid, int ownerGid, int permMask, bool createLost) {
status_t Mount(const std::string& source, const std::string& target, bool ro,
bool remount, bool executable, int ownerUid, int ownerGid, int permMask,
bool createLost) {
int rc;
unsigned long flags;
char mountData[255];
const char* c_source = source.c_str();
const char* c_target = target.c_str();
flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC;
flags |= (executable ? 0 : MS_NOEXEC);
@ -139,17 +152,17 @@ int Fat::doMount(const char *fsPath, const char *mountPoint,
"utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
ownerUid, ownerGid, permMask, permMask);
rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
rc = mount(c_source, c_target, "vfat", flags, mountData);
if (rc && errno == EROFS) {
SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
flags |= MS_RDONLY;
rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
rc = mount(c_source, c_target, "vfat", flags, mountData);
}
if (rc == 0 && createLost) {
char *lost_path;
asprintf(&lost_path, "%s/LOST.DIR", mountPoint);
asprintf(&lost_path, "%s/LOST.DIR", c_target);
if (access(lost_path, F_OK)) {
/*
* Create a LOST.DIR in the root so we have somewhere to put
@ -165,11 +178,7 @@ int Fat::doMount(const char *fsPath, const char *mountPoint,
return rc;
}
int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
if (wipe) {
Fat::wipe(fsPath, numSectors);
}
status_t Format(const std::string& source, unsigned int numSectors) {
std::vector<std::string> cmd;
cmd.push_back(kMkfsPath);
cmd.push_back("-F");
@ -185,9 +194,9 @@ int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
cmd.push_back(StringPrintf("%u", numSectors));
}
cmd.push_back(fsPath);
cmd.push_back(source);
int rc = android::vold::ForkExecvp(cmd);
int rc = ForkExecvp(cmd);
if (rc < 0) {
SLOGE("Filesystem format failed due to logwrap error");
errno = EIO;
@ -205,36 +214,6 @@ int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
return 0;
}
void Fat::wipe(const char *fsPath, unsigned int numSectors) {
unsigned long long range[2];
int fd = open(fsPath, O_RDWR | O_CLOEXEC);
if (fd == -1) {
SLOGE("Fat wipe failed to open device %s", fsPath);
return;
}
if (numSectors == 0) {
unsigned long nr_sec;
get_blkdev_size(fd, &nr_sec);
if (nr_sec > UINT32_MAX) {
SLOGE("Too many sectors for FAT: %ld", nr_sec);
close(fd);
return;
}
numSectors = nr_sec;
}
if (numSectors == 0) {
SLOGE("Fat wipe failed to determine size of %s", fsPath);
close(fd);
return;
}
range[0] = 0;
range[1] = (unsigned long long)numSectors * 512;
if (ioctl(fd, BLKDISCARD, &range) < 0) {
SLOGE("Fat wipe failed to discard blocks on %s", fsPath);
} else {
SLOGI("Fat wipe %d sectors on %s succeeded", numSectors, fsPath);
}
close(fd);
}
} // namespace vfat
} // namespace vold
} // namespace android

@ -14,22 +14,27 @@
* limitations under the License.
*/
#ifndef _FAT_H
#define _FAT_H
#include <unistd.h>
class Fat {
public:
static int check(const char *fsPath);
static int doMount(const char *fsPath, const char *mountPoint,
bool ro, bool remount, bool executable,
int ownerUid, int ownerGid, int permMask,
bool createLost);
static int format(const char *fsPath, unsigned int numSectors, bool wipe);
private:
static void wipe(const char *fsPath, unsigned int numSectors);
};
#ifndef ANDROID_VOLD_VFAT_H
#define ANDROID_VOLD_VFAT_H
#include <utils/Errors.h>
#include <string>
namespace android {
namespace vold {
namespace vfat {
bool IsSupported();
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target, bool ro,
bool remount, bool executable, int ownerUid, int ownerGid, int permMask,
bool createLost);
status_t Format(const std::string& source, unsigned int numSectors);
} // namespace vfat
} // namespace vold
} // namespace android
#endif

@ -55,6 +55,11 @@ int main(int argc, char** argv) {
LOG(INFO) << "Vold 3.0 (the awakening) firing up";
LOG(VERBOSE) << "Detected support for:"
<< (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
<< (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
<< (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
VolumeManager *vm;
CommandListener *cl;
CryptCommandListener *ccl;

Loading…
Cancel
Save