There Are Not Enough Slots Available In The System To Satisfy
- There Are Not Enough Slots Available In The System To Satisfying
- There Are Not Enough Slots Available In The System To Satisfy Best
- There Are Not Enough Slots Available In The System To Satisfy Free
- There Are Not Enough Slots Available In The System To Satisfy Cash
Total memory space is enough to satisfy a request or to reside a process in it, but it is not contiguous, so it cannot be used. 2: Internal fragmentation. Memory block assigned to process is bigger. Some portion of memory is left unused, as it cannot be used by another process. zhangchi@grid jobs$ cat hostname.o5402 - There are not enough slots available in the system to satisfy the 32 slots that were requested by the application: hostname Either request fewer slots for your application, or make more slots available for use. There are not enough slots available in the system to satisfy the 2 slots. There are not enough slots available in the system to satisfy the 2 slots.
There Are Not Enough Slots Available In The System To Satisfying
If large pages are available, the system will provide them to the application in response to page faults; if not, smaller pages will be used. Beyond that, the patch makes large pages swappable. That is not as easy as it sounds; the swap subsystem is not currently able to deal with memory in anything other than PAGESIZE units. Hello, I bought the: HP Stream Laptop PC 11-y010nr (Intel Celeron N3060, 4 GB RAM, 32 GB eMMC For my son recently. In came with Windows 10 pre-sintalled. I understood that there were some negative reviews regarding lack of memory, but this is ridiculous. After installing about 1.5 GB of programs.
In computer science, gang scheduling is a scheduling algorithm for parallel systems that schedules related threads or processes to run simultaneously on different processors. Usually these will be threads all belonging to the same process, but they may also be from different processes, where the processes could have a producer-consumer relationship or come from the same MPI program.
Gang scheduling is used to ensure that if two or more threads or processes communicate with each other, they will all be ready to communicate at the same time. If they were not gang-scheduled, then one could wait to send or receive a message to another while it is sleeping, and vice versa. When processors are over-subscribed and gang scheduling is not used within a group of processes or threads which communicate with each other, each communication event could suffer the overhead of a context switch.
Gang scheduling is based on a data structure called the Ousterhout matrix. In this matrix each row represents a time slice, and each column a processor. The threads or processes of each job are packed into a single row of the matrix.[1] During execution, coordinated context switching is performed across all nodes to switch from the processes in one row to those in the next row.
Gang scheduling is stricter than coscheduling.[2] It requires all threads of the same process to run concurrently, while coscheduling allows for fragments, which are sets of threads that do not run concurrently with the rest of the gang.
Gang scheduling was implemented and used in production mode on several parallel machines, most notably the Connection Machine CM-5.
Types[edit]
Bag of gangs (BoG)[edit]
In gang scheduling, one to one mapping happens, which means each task will be mapped to a processor. Usually, jobs are considered as independent gangs, but with a bag of gangs scheme, all the gangs can be combined and sent together to the system. When jobs are executed in the system, the execution can never be completed until and unless all the gangs that belong to the same BoG complete their executions.[3] Thus, if one gang belonging to some job completes its execution, it will have to wait until all the gangs complete their executions. This leads to increased synchronization delay overhead.
Response time of Bag of Gangs is defined as the time interval from the arrival of the BoG at the grid dispatcher to the completion of jobs of all of the sub-gangs which belong to the BoG. The average response time is defined as follows:
Response Time (RT)=.[3]
The response time is further affected when a priority job arrives. Whenever a priority job arrives at the system, that job will be given priority with respect to all other jobs, even over the ones which are currently being executed on the processors. In this case, when a priority job arrives, the sub-gang which is currently executing on the system will be stopped and all the progress that has been made will be lost and need to be redone. This interruption of the job will further delay the total response time of the BoG.[3]
Adapted first come first served (AFCFS)[edit]
Adapted first come first served (AFCFS) scheme is the adapted version of first come and first serve scheme. As per the first-come, first-served scheme, whichever job that comes first will be forwarded for execution. But in the AFCFS scheme, once a job arrives at the system, the job will not be scheduled unless and until enough processors are available for the execution of the respective job.[3] When a large job arrives at the system and is present at the start of the ready queue but not enough processors are available, then an AFCFS policy will schedule the smaller job for which enough processors are available, even if that job is at the back of the queue. In other words, this scheme favors smaller jobs as compared to larger jobs based on the availability of processor, thus this will leads to increased fragmentation in the system.[3][4]
Largest gang first served (LGFS)[edit]
In the above execution scheme, the tasks which correspond to increasing job size are placed in a queue, with the tasks belonging to the largest gang scheduled first, but this method of execution tends to lead to the starvation of resources of smaller jobs and is therefore unfit to be executed in systems where the number of processors is comparatively low.[5]
The AFCFS and LGFS also have to deal with possible processor failure. In such a case, tasks executing on that processor are submitted to other processors for execution. The tasks wait in the head of the queue on these processors while the current processor is being repaired.
There are two scenarios which emerge from the above issue:[5]
- Blocking case: The processors assigned to the interrupted jobs are blocked and cannot execute other jobs in their queue until the jobs from the damaged processors are cleared.[5]
- Non-blocking case: This case is incurred when the jobs already executing in the processors are processed early instead of waiting for the blocked jobs to resume execution.[5]
Paired gang scheduling[edit]
Gang scheduling while executing the I/O bound processes keeps the CPUs idle while awaiting responses from the other processors, whereas the idle processors can be utilized for executing tasks. If the gang consists of a mix of CPU and I/O Processes, since these processes interfere little in each other’s operation, algorithms can be defined to keep both the CPU and the I/O busy at the same time and exploiting parallelism. This method would present the idea of matching pairs of gangs, one I/O based and one CPU bound. Each gang would assume that it is working in isolation as they utilize different devices.[6]
Scheduling algorithm[edit]
- General case: In the general case, a central node is designated in the network to handle task allocation and the resource allocation. It maintains the information in an Ousterhout matrix. In strict gang scheduling, one row is selected at a time following which a node scheduler schedules a process in the respective cell of that row.[6]
- Paired gang: In paired gang scheduling, two rows are selected instead of one, one each of the I/O bound gang and CPU gang. It is at the discretion of the local scheduler to allot jobs to the appropriate processors in order to elicit maximum allowed parallelism.[6]
Synchronization methods[edit]
Concurrent gang scheduling (CGS)[edit]
Concurrent gang scheduling a highly scalable and versatile algorithm and assumes the existence of a synchronizer utilizing the internal clock of each node. CGS primarily consists of the following three components.[7]
- Processor/Memory module (Also called Processing Element).
- 2-way network which allows 1-1 Communication.
- A synchronizer which performs synchronization of all PE’s after a constant interval.
The synchronization algorithm is performed in two stages.[7]
- When the load changes, a dedicated time table is created by the front end scheduler.
- Local scheduler then follows the time table by switching between the jobs that have been distributed to them by the front end scheduler.
We assume the existence of a synchronizer that sends the signal to all the nodes in a cluster at a constant interval. The CGS utilizes the fact that the most common events which occur in a PC are timer interrupts and they use the same parameter to be the internal clock.[7]
- A common counter is initialized which gets incremented every time an interrupt is encountered and is designated the OS's internal clock.
- All nodes are synchronized after a checking interval 't' and utilize the internal clocks of the individual nodes.
- If after time t there is no discrepancy of the individual clock of the nodes and the global clock, time interval t is extended. Otherwise it is shortened.
- Constantly check and update checking interval t.
SHARE scheduling system[edit]
The SHARE scheduling system utilizes the internal clock system of each node and is synchronized using the NTP Protocol. The flavor of scheduling is implemented by collecting jobs with same resource requirements in a group and executing the same for a pre-defined time-slice. Incomplete jobs are pre-empted after the time slice is exhausted.[8]
The local memory of the node is utilized as the swap space for pre-empted jobs. The main advantages of the SHARE scheduled system are that it guarantees the service time for accepted jobs and supports both batch and interactive jobs.
Synchronization:
Each gang of processes utilizing the same resources are mapped to a different processor. The SHARE system primarily consists of three collaborating modules.[8]
- A global scheduler: This scheduler directs the local scheduler the specific order in which to execute their processes (local gang members).
- A local scheduler: After the local scheduler is provided the jobs to execute by the global scheduler, it ensures that only one of the parallel process is executed at any one of the processors in a given time slot. The local scheduler requires a context switch to preempt a job once its time slice has expired and swap a new one in its place.
- Interface to the communication system: The communication subsystem must satisfy several requirements which greatly increase the overhead requirements of the scheduler. They primarily consist of:
- Efficiency: Must expose hardware performance of the interconnect to the client level.
- Access Control: Must manage access to the communication subsystem
- Protection and Security: The interconnect must maintain separation of the processors by not allowing one to affect the performance of another.
- Multi-Protocol: the interconnect must be able to map various protocols simultaneously to cater to different client needs.
Packing criteria[edit]
A new slot is created when we cannot pack the job into the available slot. In case, a new slot is opened even if the job can be packed in the available slot, then the run fraction which is equal to one over the number of slots used will increase. Therefore, certain algorithms have been devised on packing criteria and are mentioned below:
Capacity based algorithm[edit]
This algorithm monitors the slots capacity and decides whether there is any need of opening a new slot. There are two variants on this algorithm:
1. First fit. Here, the used slots are checked for capacity in a sequential order then the first one which is having sufficient capacity is chosen. If none of the available slots have enough capacity, a new slot is opened and the processing elements (PE) are allocated in the slot in sequential order.[9]
2. Best fit. Unlike first fit, the used slots are sorted based on capacity, but not in sequential order. The slot with the smallest sufficient capacity is chosen. If none of the used slots have sufficient capacity, then only one new slot is opened. Once the new slot is opened, the processing elements (PEs) are allocated in the slot in sequential order as per the previous algorithm.[9]
Left-right based algorithms[edit]
This algorithm is a modified version of the best fit algorithm. In the best fit algorithm, the PEs are allocated in a sequential order, but in this algorithm, the PEs can be inserted from both directions so as to reduce the overlap between different sets of PEs assigned to different jobs.[9]
1. Left-right by size. Here, the PEs can be inserted in sequential order and in reverse sequential order based on the size of the job. If the size of the job is small, the PEs are inserted from left to right and if the job is large, the PEs are inserted from right to left.[9]
2. Left-right by slots. Unlike the previous algorithm, where the choice was based on the size of the job, here the choice is dependent on the slot. Now, slots are indicated as being filled, i.e. being filled from the left or from the right. The PEs are allocated to the job in the same order. The number of slots on both sides is approximately equal, so when a new slot is opened, the direction is indicated based on the number of slots in both direction.[9]
There Are Not Enough Slots Available In The System To Satisfy Best
Load based algorithms[edit]
Both the capacity-based and left-right based algorithms do not accommodate the load on individual PEs. Load-based algorithms take into account the load on the individual PE while tracking the overlap between sets of PEs assigned to different jobs.[9]
1. Minimal maximum load. In this scheme, PEs are sorted based on the load on them that each job will have on the PEs. The availability of the free PEs in the slot determines the capacity of the slot. Suppose that PEs are allocated to a job which has threads, the PE in the load order (last one) will determine the maximum load that any PE can have which is available in the slot. The slot which has minimal maximum load on any PE is chosen and a number of least loaded free PEs are used in the slot.[9]
2. Minimal average load. Unlike the previous scheme, in which slots were chosen based on the minimal maximum load on PE, here slots are chosen based on the average of the load on the least loaded PEs.[9]
Buddy based algorithm[edit]
In this algorithm the PEs are assigned in clusters, not individually. The PEs are first partitioned into groups that are power of two. Each member of the group will be assigned a controller and when a job of size n arrives, it is assigned to a controller of size 2[lg 2] (the smallest power to 2 that is larger than or equal to n). The controller is assigned by first sorting all the used slots, and then identifying groups of 2[lg 2] contiguous free processors. If a controller has all the PEs free in some of the slots, then only a newly arrived job will be assigned to that controller. Otherwise a new slot is opened.[9]
Migration based algorithm[edit]
In all the above-mentioned algorithms, the initial placement policy is fixed and jobs are allocated to the PEs based on that. However, this scheme migrates jobs from one set of PEs to another set of PEs, which in turn improves the run fraction of the system. [9]
See also[edit]
References[edit]
- ^Dror G. Feitelson (1996). Packing schemes for gang scheduling. In Job Scheduling Strategies for Parallel Processing, Springer-Verlag Lecture Notes in Computer Science Vol. 1162, pp. 89-110.
- ^Feitelson, Dror G.; Rudolph, Larry (1992). 'Gang Scheduling Performance Benefits for Fine-Grain Synchronization'. Journal of Parallel and Distributed Computing. 16 (4): 306–318. CiteSeerX10.1.1.79.7070. doi:10.1016/0743-7315(92)90014-e.
- ^ abcdePapazachos, Zafeirios C.; Karatza, Helen D. (August 2010). 'Performance evaluation of bag of gangs scheduling in a heterogeneous distributed system'. Journal of Systems and Software. 83 (8): 1346–1354. doi:10.1016/j.jss.2010.01.009.
- ^Zafeirios C. Papazachos, Helen D. Karatza, 'Performance evaluation of gang scheduling in a two-cluster system with migrations', IPDPS, 2009, Parallel and Distributed Processing Symposium, International, Parallel and Distributed Processing Symposium, International 2009, pp. 1-8, doi:10.1109/IPDPS.2009.5161172
- ^ abcd'Performance Analysis of Gang Scheduling in a Distributed System under Processor Failures'(PDF).
- ^ abc'Paired Gang Scheduling'(PDF).
- ^ abcHyoudou, Kazuki; Kozakai, Yasuyuki; Nakayama, Yasuichi (2007). 'An Implementation of a Concurrent Gang Scheduler for a PC-Based Cluster System'. Systems and Computers in Japan. 38 (3): 39–48. doi:10.1002/scj.20458.
- ^ abSociety, Ieee Computer (1996). Gang Scheduling for Highly Efficient Distributed Multiprocessor Systems. Frontiers '96. pp. 4–. ISBN9780818675515.
- ^ abcdefghij'Packing Schemes for Gang Scheduling'(PDF).
A/B system updates, also known as seamless updates, ensure a workable booting system remains on the disk during an over-the-air (OTA) update. This approach reduces the likelihood of an inactive device after an update, which means fewer device replacements and device reflashes at repair and warranty centers. Other commercial-grade operating systems such as ChromeOS also use A/B updates successfully.
For more information about A/B system updates and how they work, see Partition selection (slots).
A/B system updates provide the following benefits:
- OTA updates can occur while the system is running, without interrupting the user. Users can continue to use their devices during an OTA—the only downtime during an update is when the device reboots into the updated disk partition.
- After an update, rebooting takes no longer than a regular reboot.
- If an OTA fails to apply (for example, because of a bad flash), the user will not be affected. The user will continue to run the old OS, and the client is free to re-attempt the update.
- If an OTA update is applied but fails to boot, the device will reboot back into the old partition and remains usable. The client is free to re-attempt the update.
- Any errors (such as I/O errors) affect only the unused partition set and can be retried. Such errors also become less likely because the I/O load is deliberately low to avoid degrading the user experience.
- Updates can be streamed to A/B devices, removing the need to download the package before installing it. Streaming means it's not necessary for the user to have enough free space to store the update package on
/data
or/cache
. - The cache partition is no longer used to store OTA update packages, so there is no need to ensure that the cache partition is large enough for future updates.
- dm-verity guarantees a device will boot an uncorrupted image. If a device doesn't boot due to a bad OTA or dm-verity issue, the device can reboot into an old image. (Android Verified Boot does not require A/B updates.)
About A/B system updates
A/B updates require changes to both the client and the system. The OTA package server, however, should not require changes: update packages are still served over HTTPS. For devices using Google's OTA infrastructure, the system changes are all in AOSP, and the client code is provided by Google Play services. OEMs not using Google's OTA infrastructure will be able to reuse the AOSP system code but will need to supply their own client.
For OEMs supplying their own client, the client needs to:
- Decide when to take an update. Because A/B updates happen in the background, they are no longer user-initiated. To avoid disrupting users, it is recommended that updates are scheduled when the device is in idle maintenance mode, such as overnight, and on Wi-Fi. However, your client can use any heuristics you want.
- Check in with your OTA package servers and determine whether an update is available. This should be mostly the same as your existing client code, except that you will want to signal that the device supports A/B. (Google's client also includes a Check now button for users to check for the latest update.)
- Call
update_engine
with the HTTPS URL for your update package, assuming one is available.update_engine
will update the raw blocks on the currently unused partition as it streams the update package. - Report installation successes or failures to your servers, based on the
update_engine
result code. If the update is applied successfully,update_engine
will tell the bootloader to boot into the new OS on the next reboot. The bootloader will fallback to the old OS if the new OS fails to boot, so no work is required from the client. If the update fails, the client needs to decide when (and whether) to try again, based on the detailed error code. For example, a good client could recognize that a partial ('diff') OTA package fails and try a full OTA package instead.
Optionally, the client can:
- Show a notification asking the user to reboot. If you want to implement a policy where the user is encouraged to routinely update, then this notification can be added to your client. If the client does not prompt users, then users will get the update next time they reboot anyway. (Google's client has a per-update configurable delay.)
- Show a notification telling users whether they booted into a new OS version or whether they were expected to do so but fell back to the old OS version. (Google's client typically does neither.)
On the system side, A/B system updates affect the following:
- Partition selection (slots), the
update_engine
daemon, and bootloader interactions (described below) - Build process and OTA update package generation (described in Implementing A/B Updates)
Partition selection (slots)
A/B system updates use two sets of partitions referred to as slots (normally slot A and slot B). The system runs from the current slot while the partitions in the unused slot are not accessed by the running system during normal operation. This approach makes updates fault resistant by keeping the unused slot as a fallback: If an error occurs during or immediately after an update, the system can rollback to the old slot and continue to have a working system. To achieve this goal, no partition used by the current slot should be updated as part of the OTA update (including partitions for which there is only one copy).
Each slot has a bootable attribute that states whether the slot contains a correct system from which the device can boot. The current slot is bootable when the system is running, but the other slot may have an old (still correct) version of the system, a newer version, or invalid data. Regardless of what the current slot is, there is one slot that is the active slot (the one the bootloader will boot form on the next boot) or the preferred slot.
Each slot also has a successful attribute set by the user space, which is relevant only if the slot is also bootable. A successful slot should be able to boot, run, and update itself. A bootable slot that was not marked as successful (after several attempts were made to boot from it) should be marked as unbootable by the bootloader, including changing the active slot to another bootable slot (normally to the slot running immediately before the attempt to boot into the new, active one). The specific details of the interface are defined in boot_control.h
.
Update engine daemon
A/B system updates use a background daemon called update_engine
to prepare the system to boot into a new, updated version. This daemon can perform the following actions:
- Read from the current slot A/B partitions and write any data to the unused slot A/B partitions as instructed by the OTA package.
- Call the
boot_control
interface in a pre-defined workflow. - Run a post-install program from the new partition after writing all the unused slot partitions, as instructed by the OTA package. (For details, see Post-installation).
As the update_engine
daemon is not involved in the boot process itself, it is limited in what it can do during an update by the SELinux policies and features in the current slot (such policies and features can't be updated until the system boots into a new version). To maintain a robust system, the update process should not modify the partition table, the contents of partitions in the current slot, or the contents of non-A/B partitions that can't be wiped with a factory reset.
Update engine source
The update_engine
source is located in system/update_engine
. The A/B OTA dexopt files are split between installd
and a package manager:
frameworks/native/cmds/installd/
ota* includes the postinstall script, the binary for chroot, the installd clone that calls dex2oat, the post-OTA move-artifacts script, and the rc file for the move script.frameworks/base/services/core/java/com/android/server/pm/OtaDexoptService.java
(plusOtaDexoptShellCommand
) is the package manager that prepares dex2oat commands for applications.
For a working example, refer to /device/google/marlin/device-common.mk
.
Update engine logs
For Android 8.x releases and earlier, the update_engine
logs can be found in logcat
and in the bug report. To make the update_engine
logs available in the file system, patch the following changes into your build:
There Are Not Enough Slots Available In The System To Satisfy Free
These changes save a copy of the most recent update_engine
log to /data/misc/update_engine_log/update_engine.YEAR-TIME
. In addition to the current log, the five most recent logs are saved under /data/misc/update_engine_log/
. Users with the log group ID will be able to access the file system logs.
Bootloader interactions
The boot_control
HAL is used by update_engine
(and possibly other daemons) to instruct the bootloader what to boot from. Common example scenarios and their associated states include the following:
- Normal case: The system is running from its current slot, either slot A or B. No updates have been applied so far. The system's current slot is bootable, successful, and the active slot.
- Update in progress: The system is running from slot B, so slot B is the bootable, successful, and active slot. Slot A was marked as unbootable since the contents of slot A are being updated but not yet completed. A reboot in this state should continue booting from slot B.
- Update applied, reboot pending: The system is running from slot B, slot B is bootable and successful, but slot A was marked as active (and therefore is marked as bootable). Slot A is not yet marked as successful and some number of attempts to boot from slot A should be made by the bootloader.
- System rebooted into new update: The system is running from slot A for the first time, slot B is still bootable and successful while slot A is only bootable, and still active but not successful. A user space daemon,
update_verifier
, should mark slot A as successful after some checks are made.
Streaming update support
User devices don't always have enough space on /data
to download the update package. As neither OEMs nor users want to waste space on a /cache
partition, some users go without updates because the device has nowhere to store the update package. To address this issue, Android 8.0 added support for streaming A/B updates that write blocks directly to the B partition as they are downloaded, without having to store the blocks on /data
. Streaming A/B updates need almost no temporary storage and require just enough storage for roughly 100 KiB of metadata.
To enable streaming updates in Android 7.1, cherrypick the following patches:
These patches are required to support streaming A/B updates in Android 7.1 and later whether using Google Mobile Services (GMS) or any other update client.
Life of an A/B update
The update process starts when an OTA package (referred to in code as a payload) is available for downloading. Policies in the device may defer the payload download and application based on battery level, user activity, charging status, or other policies. In addition, because the update runs in the background, users might not know an update is in progress. All of this means the update process might be interrupted at any point due to policies, unexpected reboots, or user actions.
There Are Not Enough Slots Available In The System To Satisfy Cash
Optionally, metadata in the OTA package itself indicates the update can be streamed; the same package can also be used for non-streaming installation. The server may use the metadata to tell the client it's streaming so the client will hand off the OTA to update_engine
correctly. Device manufacturers with their own server and client can enable streaming updates by ensuring the server identifies the update is streaming (or assumes all updates are streaming) and the client makes the correct call to update_engine
for streaming. Manufacturers can use the fact that the package is of the streaming variant to send a flag to the client to trigger hand off to the framework side as streaming.
After a payload is available, the update process is as follows:
Step | Activities |
---|---|
1 | The current slot (or 'source slot') is marked as successful (if not already marked) with markBootSuccessful() . |
2 | The unused slot (or 'target slot') is marked as unbootable by calling the function setSlotAsUnbootable() . The current slot is always marked as successful at the beginning of the update to prevent the bootloader from falling back to the unused slot, which will soon have invalid data. If the system has reached the point where it can start applying an update, the current slot is marked as successful even if other major components are broken (such as the UI in a crash loop) as it is possible to push new software to fix these problems. The update payload is an opaque blob with the instructions to update to the new version. The update payload consists of the following:
|
3 | The payload metadata is downloaded. |
4 | For each operation defined in the metadata, in order, the associated data (if any) is downloaded to memory, the operation is applied, and the associated memory is discarded. |
5 | The whole partitions are re-read and verified against the expected hash. |
6 | The post-install step (if any) is run. In the case of an error during the execution of any step, the update fails and is re-attempted with possibly a different payload. If all the steps so far have succeeded, the update succeeds and the last step is executed. |
7 | The unused slot is marked as active by calling setActiveBootSlot() . Marking the unused slot as active doesn't mean it will finish booting. The bootloader (or system itself) can switch the active slot back if it doesn't read a successful state. |
8 | Post-installation (described below) involves running a program from the 'new update' version while still running in the old version. If defined in the OTA package, this step is mandatory and the program must return with exit code 0 ; otherwise, the update fails. |
9 | After the system successfully boots far enough into the new slot and finishes the post-reboot checks, the now current slot (formerly the 'target slot') is marked as successful by calling markBootSuccessful() . |
Post-installation
For every partition where a post-install step is defined, update_engine
mounts the new partition into a specific location and executes the program specified in the OTA relative to the mounted partition. For example, if the post-install program is defined as usr/bin/postinstall
in the system partition, this partition from the unused slot will be mounted in a fixed location (such as /postinstall_mount
) and the /postinstall_mount/usr/bin/postinstall
command is executed.
For post-installation to succeed, the old kernel must be able to:
- Mount the new filesystem format. The filesystem type cannot change unless there's support for it in the old kernel, including details such as the compression algorithm used if using a compressed filesystem (i.e. SquashFS).
- Understand the new partition's post-install program format. If using an Executable and Linkable Format (ELF) binary, it should be compatible with the old kernel (e.g. a 64-bit new program running on an old 32-bit kernel if the architecture switched from 32- to 64-bit builds). Unless the loader (
ld
) is instructed to use other paths or build a static binary, libraries will be loaded from the old system image and not the new one.
For example, you could use a shell script as a post-install program interpreted by the old system's shell binary with a #!
marker at the top), then set up library paths from the new environment for executing a more complex binary post-install program. Alternatively, you could run the post-install step from a dedicated smaller partition to enable the filesystem format in the main system partition to be updated without incurring backward compatibility issues or stepping-stone updates; this would allow users to update directly to the latest version from a factory image.
The new post-install program is limited by the SELinux policies defined in the old system. As such, the post-install step is suitable for performing tasks required by design on a given device or other best-effort tasks (i.e. updating the A/B-capable firmware or bootloader, preparing copies of databases for the new version, etc.). The post-install step is not suitable for one-off bug fixes before reboot that require unforeseen permissions.
The selected post-install program runs in the postinstall
SELinux context. All the files in the new mounted partition will be tagged with postinstall_file
, regardless of what their attributes are after rebooting into that new system. Changes to the SELinux attributes in the new system won't impact the post-install step. If the post-install program needs extra permissions, those must be added to the post-install context.
After reboot
After rebooting, update_verifier
triggers the integrity check using dm-verity. This check starts before zygote to avoid Java services making any irreversible changes that would prevent a safe rollback. During this process, bootloader and kernel may also trigger a reboot if verified boot or dm-verity detect any corruption. After the check completes, update_verifier
marks the boot successful.
update_verifier
will read only the blocks listed in /data/ota_package/care_map.txt
, which is included in an A/B OTA package when using the AOSP code. The Java system update client, such as GmsCore, extracts care_map.txt
, sets up the access permission before rebooting the device, and deletes the extracted file after the system successfully boots into the new version.