void NetlinkHandler::onEvent(NetlinkEvent *evt) {
VolumeManager *vm = VolumeManager::Instance(); const char *subsys = evt->getSubsystem();
if (!subsys) {
SLOGW(
" No subsystem found in netlink event ");
return;
}
SLOGD(
" NetlinkHandler:OnEvent subsys values is %s ",subsys);
if (!strcmp(subsys,
" block ")) {
SLOGD(
" NetlinkHandler:onEvent ");
vm->handleBlockEvent(evt); }
}
在NetlinkHandler 里面得一个VolumeManager,当收到的命令为block时调用VolumnManager的handleBlockEvent,如上加红加粗的代码。
handleBlockEvent实则是通过一个循环将事先将main事先读取的配置文件:etc/vold.fstab存进VolumeCollection,得到VolumeCollection的对象,然后调用Volume 的handleBlockEvent,如代码:
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
const char *devpath = evt->findParam(
" DEVPATH ");
/* Lookup a volume to handle this device */ VolumeCollection::iterator it;
bool hit =
false;
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
if (!
(*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
SLOGD(
" Device '%s' event handled by volume %s\n ", devpath, (*it)->getLabel());
#endif hit =
true;
break;
}
}
if (!hit) {
#ifdef NETLINK_DEBUG
SLOGW(
" No volumes handled block event for '%s' ", devpath);
#endif }
int Volume::handleBlockEvent(NetlinkEvent *evt) {
errno = ENOSYS;
return -
1;
看起来好像没做什么事,其实真的实现在于Volume 的子类,DirectVolume,DirectVolme 中重写了handleBlockEvent,看代码:
int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
const char *dp = evt->findParam(
" DEVPATH ");
PathCollection::iterator it;
for (it = mPaths->begin(); it != mPaths->end(); ++it) {
if (!strncmp(dp, *it, strlen(*it))) {
/* We can handle this disk */ int action = evt->getAction();
const char *devtype = evt->findParam(
" DEVTYPE ");
if (action == NetlinkEvent::NlActionAdd) {
int major = atoi(evt->findParam(
" MAJOR "));
int minor = atoi(evt->findParam(
" MINOR "));
char nodepath[
255];
snprintf(nodepath,
sizeof(nodepath),
" /dev/block/vold/%d:%d ",
major, minor);
if (createDeviceNode(nodepath, major, minor)) {
SLOGE(
" Error making device node '%s' (%s) ", nodepath,
strerror(errno));
}
if (!strcmp(devtype,
" disk ")) {
handleDiskAdded(dp, evt);
}
else {
handlePartitionAdded(dp, evt);
}
}
else if (action == NetlinkEvent::NlActionRemove) {
if (!strcmp(devtype,
" disk ")) {
handleDiskRemoved(dp, evt);
}
else {
SLOGD(
" DirectVolume:handleBlockEvent--->handlePartitionRemoved ");
handlePartitionRemoved(dp, evt);
}
}
else if (action == NetlinkEvent::NlActionChange) {
if (!strcmp(devtype,
" disk ")) {
handleDiskChanged(dp, evt);
}
else {
handlePartitionChanged(dp, evt);
}
}
else {
SLOGW(
" Ignoring non add/remove/change event ");
}
return 0;
}
}
errno = ENODEV;
return -
1;
}
void DirectVolume::handlePartitionRemoved(
const char *devpath, NetlinkEvent *evt) {
if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {
/* * Yikes, our mounted partition is going away! */ snprintf(msg,
sizeof(msg),
" Volume %s %s bad removal (%d:%d) ",
getLabel(), getMountpoint(), major, minor);
SLOGD(
" DirectVolume:(dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev:%d,msg is :%s. ",mCurrentlyMountedKdev,msg);
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, msg, false); if (mVm->cleanupAsec(
this,
true)) {
SLOGE(
" Failed to cleanup ASEC - unmount will probably fail! ");
}
if (
Volume::unmountVol(true, false)) {
SLOGE(
" Failed to unmount volume on bad removal (%s) ",
strerror(errno));
// XXX: At this point we're screwed for now }
else {
SLOGD(
" Crisis averted ");
}
}
}
int Volume::unmountVol(
bool force,
bool revert) {
setState(Volume::State_Unmounting);
}
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
msg,
false);