Added support for ext4 ASEC resizing.
ASECs formatted as ext4 can now be resized using vdc asec resize. Refactored some common code. Requires resize2fs. Change-Id: Ie78bb6015114a7bc4af42b16d1f299322ffc1e2a Signed-off-by: Daniel Rosenberg <drosen@google.com>
This commit is contained in:
parent
73d7a02dc6
commit
fcd34a0ddd
8 changed files with 338 additions and 115 deletions
|
@ -359,6 +359,14 @@ int CommandListener::AsecCmd::runCommand(SocketClient *cli,
|
|||
unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
|
||||
const bool isExternal = (atoi(argv[7]) == 1);
|
||||
rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]), isExternal);
|
||||
} else if (!strcmp(argv[1], "resize")) {
|
||||
dumpArgs(argc, argv, -1);
|
||||
if (argc != 5) {
|
||||
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec resize <container-id> <size_mb> <key>", false);
|
||||
return 0;
|
||||
}
|
||||
unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
|
||||
rc = vm->resizeAsec(argv[2], numSectors, argv[4]);
|
||||
} else if (!strcmp(argv[1], "finalize")) {
|
||||
dumpArgs(argc, argv, -1);
|
||||
if (argc != 3) {
|
||||
|
|
|
@ -125,8 +125,8 @@ void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
|
|||
io->flags = flags;
|
||||
if (name) {
|
||||
size_t ret = strlcpy(io->name, name, sizeof(io->name));
|
||||
if (ret >= sizeof(io->name))
|
||||
abort();
|
||||
if (ret >= sizeof(io->name))
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
46
Ext4.cpp
46
Ext4.cpp
|
@ -43,7 +43,8 @@
|
|||
#include "Ext4.h"
|
||||
#include "VoldUtil.h"
|
||||
|
||||
#define MKEXT4FS_PATH "/system/bin/make_ext4fs";
|
||||
#define MKEXT4FS_PATH "/system/bin/make_ext4fs"
|
||||
#define RESIZE2FS_PATH "/system/bin/resize2fs"
|
||||
|
||||
int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount,
|
||||
bool executable) {
|
||||
|
@ -67,6 +68,49 @@ int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remo
|
|||
return rc;
|
||||
}
|
||||
|
||||
int Ext4::resize(const char *fspath, unsigned int numSectors) {
|
||||
const char *args[4];
|
||||
char* size_str;
|
||||
int rc;
|
||||
int status;
|
||||
|
||||
args[0] = RESIZE2FS_PATH;
|
||||
args[1] = "-f";
|
||||
args[2] = fspath;
|
||||
if (asprintf(&size_str, "%ds", numSectors) < 0)
|
||||
{
|
||||
SLOGE("Filesystem (ext4) resize failed to set size");
|
||||
return -1;
|
||||
}
|
||||
args[3] = size_str;
|
||||
rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false,
|
||||
true);
|
||||
free(size_str);
|
||||
if (rc != 0) {
|
||||
SLOGE("Filesystem (ext4) resize failed due to logwrap error");
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!WIFEXITED(status)) {
|
||||
SLOGE("Filesystem (ext4) resize did not exit properly");
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = WEXITSTATUS(status);
|
||||
|
||||
if (status == 0) {
|
||||
SLOGI("Filesystem (ext4) resized OK");
|
||||
return 0;
|
||||
} else {
|
||||
SLOGE("Resize (ext4) failed (unknown exit code %d)", status);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) {
|
||||
int fd;
|
||||
const char *args[7];
|
||||
|
|
1
Ext4.h
1
Ext4.h
|
@ -24,6 +24,7 @@ public:
|
|||
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);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
28
Loop.cpp
28
Loop.cpp
|
@ -249,6 +249,34 @@ int Loop::createImageFile(const char *file, unsigned int numSectors) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Loop::resizeImageFile(const char *file, unsigned int numSectors) {
|
||||
int fd;
|
||||
|
||||
if ((fd = open(file, O_RDWR)) < 0) {
|
||||
SLOGE("Error opening imagefile (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLOGD("Attempting to increase size of %s to %d sectors.", file, numSectors);
|
||||
|
||||
if (fallocate(fd, 0, 0, numSectors * 512)) {
|
||||
if (errno == ENOSYS) {
|
||||
SLOGW("fallocate not found. Falling back to ftruncate.");
|
||||
if (ftruncate(fd, numSectors * 512) < 0) {
|
||||
SLOGE("Error truncating imagefile (%s)", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SLOGE("Error allocating space (%s)", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Loop::lookupInfo(const char *loopDevice, struct asec_superblock *sb, unsigned int *nr_sec) {
|
||||
int fd;
|
||||
struct asec_superblock buffer;
|
||||
|
|
1
Loop.h
1
Loop.h
|
@ -32,6 +32,7 @@ public:
|
|||
static int destroyByDevice(const char *loopDevice);
|
||||
static int destroyByFile(const char *loopFile);
|
||||
static int createImageFile(const char *file, unsigned int numSectors);
|
||||
static int resizeImageFile(const char *file, unsigned int numSectors);
|
||||
|
||||
static int dumpState(SocketClient *c);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <linux/kdev_t.h>
|
||||
|
@ -57,6 +58,101 @@
|
|||
#define ROUND_UP_POWER_OF_2(number, po2) (((!!(number & ((1U << po2) - 1))) << po2)\
|
||||
+ (number & (~((1U << po2) - 1))))
|
||||
|
||||
/* writes superblock at end of file or device given by name */
|
||||
static int writeSuperBlock(const char* name, struct asec_superblock *sb, unsigned int numImgSectors) {
|
||||
int sbfd = open(name, O_RDWR);
|
||||
if (sbfd < 0) {
|
||||
SLOGE("Failed to open %s for superblock write (%s)", name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
|
||||
SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
|
||||
close(sbfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(sbfd, sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
|
||||
SLOGE("Failed to write superblock (%s)", strerror(errno));
|
||||
close(sbfd);
|
||||
return -1;
|
||||
}
|
||||
close(sbfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adjustSectorNumExt4(unsigned numSectors) {
|
||||
return ROUND_UP_POWER_OF_2(numSectors, 3);
|
||||
}
|
||||
|
||||
static int adjustSectorNumFAT(unsigned numSectors) {
|
||||
/*
|
||||
* Add some headroom
|
||||
*/
|
||||
unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
|
||||
numSectors += fatSize + 2;
|
||||
/*
|
||||
* FAT is aligned to 32 kb with 512b sectors.
|
||||
*/
|
||||
return ROUND_UP_POWER_OF_2(numSectors, 6);
|
||||
}
|
||||
|
||||
static int setupLoopDevice(char* buffer, size_t len, const char* asecFileName, const char* idHash, bool debug) {
|
||||
if (Loop::lookupActive(idHash, buffer, len)) {
|
||||
if (Loop::create(idHash, asecFileName, buffer, len)) {
|
||||
SLOGE("ASEC loop device creation failed for %s (%s)", asecFileName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (debug) {
|
||||
SLOGD("New loop device created at %s", buffer);
|
||||
}
|
||||
} else {
|
||||
if (debug) {
|
||||
SLOGD("Found active loopback for %s at %s", asecFileName, buffer);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setupDevMapperDevice(char* buffer, size_t len, const char* loopDevice, const char* asecFileName, const char* key, const char* idHash , int numImgSectors, bool* createdDMDevice, bool debug) {
|
||||
if (strcmp(key, "none")) {
|
||||
if (Devmapper::lookupActive(idHash, buffer, len)) {
|
||||
if (Devmapper::create(idHash, loopDevice, key, numImgSectors,
|
||||
buffer, len)) {
|
||||
SLOGE("ASEC device mapping failed for %s (%s)", asecFileName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (debug) {
|
||||
SLOGD("New devmapper instance created at %s", buffer);
|
||||
}
|
||||
} else {
|
||||
if (debug) {
|
||||
SLOGD("Found active devmapper for %s at %s", asecFileName, buffer);
|
||||
}
|
||||
}
|
||||
*createdDMDevice = true;
|
||||
} else {
|
||||
strcpy(buffer, loopDevice);
|
||||
*createdDMDevice = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void waitForDevMapper(const char *dmDevice) {
|
||||
/*
|
||||
* Wait for the device mapper node to be created. Sometimes it takes a
|
||||
* while. Wait for up to 1 second. We could also inspect incoming uevents,
|
||||
* but that would take more effort.
|
||||
*/
|
||||
int tries = 25;
|
||||
while (tries--) {
|
||||
if (!access(dmDevice, F_OK) || errno != ENOENT) {
|
||||
break;
|
||||
}
|
||||
usleep(40 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
VolumeManager *VolumeManager::sInstance = NULL;
|
||||
|
||||
VolumeManager *VolumeManager::Instance() {
|
||||
|
@ -333,19 +429,11 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add some headroom
|
||||
* This is likely off by a bit, and we may want to do something different for ext4
|
||||
*/
|
||||
unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
|
||||
unsigned numImgSectors = numSectors + fatSize + 2;
|
||||
/*
|
||||
* ext4 is aligned to 4kb. fat is aligned to 32kb. Sectors are 512b.
|
||||
*/
|
||||
unsigned numImgSectors;
|
||||
if (usingExt4)
|
||||
numImgSectors = ROUND_UP_POWER_OF_2(numImgSectors, 3);
|
||||
numImgSectors = adjustSectorNumExt4(numSectors);
|
||||
else
|
||||
numImgSectors = ROUND_UP_POWER_OF_2(numImgSectors, 6);
|
||||
numImgSectors = adjustSectorNumFAT(numSectors);
|
||||
|
||||
// Add +1 for our superblock which is at the end
|
||||
if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
|
||||
|
@ -389,10 +477,7 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
|
|||
/*
|
||||
* Drop down the superblock at the end of the file
|
||||
*/
|
||||
|
||||
int sbfd = open(loopDevice, O_RDWR);
|
||||
if (sbfd < 0) {
|
||||
SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
|
||||
if (writeSuperBlock(loopDevice, &sb, numImgSectors)) {
|
||||
if (cleanupDm) {
|
||||
Devmapper::destroy(idHash);
|
||||
}
|
||||
|
@ -401,29 +486,6 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
|
||||
close(sbfd);
|
||||
SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
|
||||
if (cleanupDm) {
|
||||
Devmapper::destroy(idHash);
|
||||
}
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
unlink(asecFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
|
||||
close(sbfd);
|
||||
SLOGE("Failed to write superblock (%s)", strerror(errno));
|
||||
if (cleanupDm) {
|
||||
Devmapper::destroy(idHash);
|
||||
}
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
unlink(asecFileName);
|
||||
return -1;
|
||||
}
|
||||
close(sbfd);
|
||||
|
||||
if (wantFilesystem) {
|
||||
int formatStatus;
|
||||
char mountPoint[255];
|
||||
|
@ -503,6 +565,146 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha
|
|||
return 0;
|
||||
}
|
||||
|
||||
int VolumeManager::resizeAsec(const char *id, unsigned numSectors, const char *key) {
|
||||
char asecFileName[255];
|
||||
char mountPoint[255];
|
||||
bool cleanupDm = false;
|
||||
|
||||
if (!isLegalAsecId(id)) {
|
||||
SLOGE("resizeAsec: Invalid asec id \"%s\"", id);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (findAsec(id, asecFileName, sizeof(asecFileName))) {
|
||||
SLOGE("Couldn't find ASEC %s", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int written = snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
|
||||
if ((written < 0) || (size_t(written) >= sizeof(mountPoint))) {
|
||||
SLOGE("ASEC resize failed for %s: couldn't construct mountpoint", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (isMountpointMounted(mountPoint)) {
|
||||
SLOGE("ASEC %s mounted. Unmount before resizing", id);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct asec_superblock sb;
|
||||
int fd;
|
||||
unsigned int oldNumSec = 0;
|
||||
|
||||
if ((fd = open(asecFileName, O_RDONLY)) < 0) {
|
||||
SLOGE("Failed to open ASEC file (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat info;
|
||||
if (fstat(fd, &info) < 0) {
|
||||
SLOGE("Failed to get file size (%s)", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oldNumSec = info.st_size / 512;
|
||||
|
||||
unsigned numImgSectors;
|
||||
if (sb.c_opts & ASEC_SB_C_OPTS_EXT4)
|
||||
numImgSectors = adjustSectorNumExt4(numSectors);
|
||||
else
|
||||
numImgSectors = adjustSectorNumFAT(numSectors);
|
||||
/*
|
||||
* add one block for the superblock
|
||||
*/
|
||||
SLOGD("Resizing from %d sectors to %d sectors", oldNumSec, numImgSectors + 1);
|
||||
if (oldNumSec >= numImgSectors + 1) {
|
||||
SLOGE("Only growing is currently supported.");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to read superblock.
|
||||
*/
|
||||
memset(&sb, 0, sizeof(struct asec_superblock));
|
||||
if (lseek(fd, ((oldNumSec - 1) * 512), SEEK_SET) < 0) {
|
||||
SLOGE("lseek failed (%s)", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (read(fd, &sb, sizeof(struct asec_superblock)) != sizeof(struct asec_superblock)) {
|
||||
SLOGE("superblock read failed (%s)", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (mDebug) {
|
||||
SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
|
||||
}
|
||||
if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
|
||||
SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
|
||||
errno = EMEDIUMTYPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(sb.c_opts & ASEC_SB_C_OPTS_EXT4)) {
|
||||
SLOGE("Only ext4 partitions are supported for resize");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Loop::resizeImageFile(asecFileName, numImgSectors + 1)) {
|
||||
SLOGE("Resize of ASEC image file failed. Could not resize %s", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop down a copy of the superblock at the end of the file
|
||||
*/
|
||||
if (writeSuperBlock(asecFileName, &sb, numImgSectors))
|
||||
goto fail;
|
||||
|
||||
char idHash[33];
|
||||
if (!asecHash(id, idHash, sizeof(idHash))) {
|
||||
SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
char loopDevice[255];
|
||||
if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
|
||||
goto fail;
|
||||
|
||||
char dmDevice[255];
|
||||
|
||||
if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash, numImgSectors, &cleanupDm, mDebug)) {
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the device mapper node to be created.
|
||||
*/
|
||||
waitForDevMapper(dmDevice);
|
||||
|
||||
if (Ext4::resize(dmDevice, numImgSectors)) {
|
||||
SLOGE("Unable to resize %s (%s)", id, strerror(errno));
|
||||
if (cleanupDm) {
|
||||
Devmapper::destroy(idHash);
|
||||
}
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
Loop::resizeImageFile(asecFileName, oldNumSec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int VolumeManager::finalizeAsec(const char *id) {
|
||||
char asecFileName[255];
|
||||
char loopDevice[255];
|
||||
|
@ -1060,19 +1262,8 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
|
|||
}
|
||||
|
||||
char loopDevice[255];
|
||||
if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
|
||||
if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
|
||||
SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (mDebug) {
|
||||
SLOGD("New loop device created at %s", loopDevice);
|
||||
}
|
||||
} else {
|
||||
if (mDebug) {
|
||||
SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
|
||||
}
|
||||
}
|
||||
if (setupLoopDevice(loopDevice, sizeof(loopDevice), asecFileName, idHash, mDebug))
|
||||
return -1;
|
||||
|
||||
char dmDevice[255];
|
||||
bool cleanupDm = false;
|
||||
|
@ -1095,25 +1286,9 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
|
|||
}
|
||||
nr_sec--; // We don't want the devmapping to extend onto our superblock
|
||||
|
||||
if (strcmp(key, "none")) {
|
||||
if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
|
||||
if (Devmapper::create(idHash, loopDevice, key, nr_sec,
|
||||
dmDevice, sizeof(dmDevice))) {
|
||||
SLOGE("ASEC device mapping failed (%s)", strerror(errno));
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
return -1;
|
||||
}
|
||||
if (mDebug) {
|
||||
SLOGD("New devmapper instance created at %s", dmDevice);
|
||||
}
|
||||
} else {
|
||||
if (mDebug) {
|
||||
SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
|
||||
}
|
||||
}
|
||||
cleanupDm = true;
|
||||
} else {
|
||||
strcpy(dmDevice, loopDevice);
|
||||
if (setupDevMapperDevice(dmDevice, sizeof(dmDevice), loopDevice, asecFileName, key, idHash , nr_sec, &cleanupDm, mDebug)) {
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mkdir(mountPoint, 0000)) {
|
||||
|
@ -1128,17 +1303,9 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
|
|||
}
|
||||
|
||||
/*
|
||||
* The device mapper node needs to be created. Sometimes it takes a
|
||||
* while. Wait for up to 1 second. We could also inspect incoming uevents,
|
||||
* but that would take more effort.
|
||||
* Wait for the device mapper node to be created.
|
||||
*/
|
||||
int tries = 25;
|
||||
while (tries--) {
|
||||
if (!access(dmDevice, F_OK) || errno != ENOENT) {
|
||||
break;
|
||||
}
|
||||
usleep(40 * 1000);
|
||||
}
|
||||
waitForDevMapper(dmDevice);
|
||||
|
||||
int result;
|
||||
if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
|
||||
|
@ -1201,19 +1368,8 @@ int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
|
|||
}
|
||||
|
||||
char loopDevice[255];
|
||||
if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
|
||||
if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
|
||||
SLOGE("Image loop device creation failed (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (mDebug) {
|
||||
SLOGD("New loop device created at %s", loopDevice);
|
||||
}
|
||||
} else {
|
||||
if (mDebug) {
|
||||
SLOGD("Found active loopback for %s at %s", img, loopDevice);
|
||||
}
|
||||
}
|
||||
if (setupLoopDevice(loopDevice, sizeof(loopDevice), img, idHash, mDebug))
|
||||
return -1;
|
||||
|
||||
char dmDevice[255];
|
||||
bool cleanupDm = false;
|
||||
|
@ -1235,25 +1391,9 @@ int VolumeManager::mountObb(const char *img, const char *key, int ownerGid) {
|
|||
|
||||
close(fd);
|
||||
|
||||
if (strcmp(key, "none")) {
|
||||
if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
|
||||
if (Devmapper::create(idHash, loopDevice, key, nr_sec,
|
||||
dmDevice, sizeof(dmDevice))) {
|
||||
SLOGE("ASEC device mapping failed (%s)", strerror(errno));
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
return -1;
|
||||
}
|
||||
if (mDebug) {
|
||||
SLOGD("New devmapper instance created at %s", dmDevice);
|
||||
}
|
||||
} else {
|
||||
if (mDebug) {
|
||||
SLOGD("Found active devmapper for %s at %s", img, dmDevice);
|
||||
}
|
||||
}
|
||||
cleanupDm = true;
|
||||
} else {
|
||||
strcpy(dmDevice, loopDevice);
|
||||
if (setupDevMapperDevice(dmDevice, sizeof(loopDevice), loopDevice, img,key, idHash , nr_sec, &cleanupDm, mDebug)) {
|
||||
Loop::destroyByDevice(loopDevice);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mkdir(mountPoint, 0755)) {
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
const char **directory = NULL) const;
|
||||
int createAsec(const char *id, unsigned numSectors, const char *fstype,
|
||||
const char *key, const int ownerUid, bool isExternal);
|
||||
int resizeAsec(const char *id, unsigned numSectors, const char *key);
|
||||
int finalizeAsec(const char *id);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue