ב-Android יש שני מנגנוני עדכון: עדכוני A/B (חלקיים) ועדכונים שאינם מסוג A/B. כדי להפחית את מורכבות הקוד ולשפר את תהליך העדכון, ב-Android 11 אוחדו שני מנגנונים באמצעות A/B וירטואלי כדי לספק עדכונים חלקים מכשירים עם עלות אחסון נמוכה יותר. 12 Android אפשר להשתמש בדחיסת A/B וירטואלית כדי לדחוס מחיצות בקובצי snapshot. ב-Android 11 וב-Android 12: חלות:
- עדכוני A/B וירטואליים הם חלקיים כמו עדכוני A/B. עדכונים לגבי Virtual A/B לצמצם את משך הזמן שבו מכשיר במצב אופליין ולא ניתן לשימוש.
- אפשר להחזיר עדכוני A/B וירטואליים. אם לא ניתן להפעיל את מערכת ההפעלה החדשה, מכשירים חוזרים באופן אוטומטי לגרסה הקודמת.
- עדכוני A/B וירטואליים משתמשים בשטח נוסף מינימלי על-ידי שכפול של רק המחיצות שמשמשות את תוכנת האתחול. מחיצות אחרות הניתנות לעדכון הן snapshotted.
רקע ומינוח
הקטע הזה מגדיר את המונחים ומתאר את הטכנולוגיה שתומכת בדיקת A/B וירטואלית.
מיפוי מכשירים
מיפוי המכשירים הוא שכבת בלוק וירטואלית של Linux שמשמשת לעיתים קרובות ב-Android. ב-
מחיצות דינמיות, מחיצות כמו
/system
הם סטאק של מכשירים עם שכבות:
- בחלק התחתון של המקבץ נמצאת המחיצה הפיזית Super (לדוגמה,
/dev/block/by-name/super
). - באמצע נמצא מכשיר
dm-linear
, שמציין אילו בלוקים בסופר תיצור את המחיצה הנתונה. הכיתוב הזה מופיע בתור/dev/block/mapper/system_[a|b]
במכשיר A/B, או/dev/block/mapper/system
במכשיר ללא בדיקת A/B. - בחלק העליון נמצא מכשיר
dm-verity
, שנוצר למחיצות מאומתות. המכשיר הזה מאמת שהחסימות במכשירdm-linear
חתומות בצורה נכונה. הוא מופיע בתור/dev/block/mapper/system-verity
והוא המקור של נקודת הטעינה/system
.
איור 1 מראה איך נראית המקבץ מתחת לנקודת הטעינה של /system
.
איור 1. ערימה מתחת לנקודת הטעינה של /system
תמונת מצב
A/B וירטואלי מסתמך על dm-snapshot
, מודול מיפוי מכשירים ליצירת תמונות של
במצב של התקן האחסון. כשמשתמשים ב-dm-snapshot
, יש 4 מכשירים
הפעלה:
- מכשיר הבסיס הוא המכשיר שנשמר בתמונת מצב. בדף הזה הבסיס המכשיר הוא תמיד מחיצה דינמית, כמו מערכת או ספק.
- מכשיר העתקה על כתיבה (COW) לרישום שינויים במכשיר הבסיסי. הוא הוא יכול להיות כל גודל, אבל הוא חייב להיות גדול מספיק כדי להתאים את כל השינויים של המכשיר הבסיסי.
- מכשיר ה-snapshot נוצר באמצעות היעד
snapshot
. כותבת התקן תמונת המצב נכתבים במכשיר COW. קריאות מתמונת המצב קריאה מהמכשיר הבסיסי או ממכשיר COW, בהתאם האם הנתונים שאליהם מתבצעת גישה השתנו על ידי תמונת המצב. - מכשיר המקור נוצר באמצעות היעד
snapshot-origin
. מקרא ל: מכשיר המקור שנקרא ישירות מהמכשיר הבסיסי. כתיבה למקור כתובים ישירות למכשיר הבסיסי, אבל הנתונים המקוריים מגובים באמצעות כתיבה למכשיר COW.
איור 2. מיפוי מכשירים ל-dm-snapshot
תמונות מצב דחוסות
ב-Android מגרסה 12 ואילך, כי הדרישות של נפח האחסון מופעלות
המחיצה /data
יכולה להיות גבוהה, ניתן להפעיל תמונות מצב דחוסות
build כדי לענות על דרישות השטח הגבוהות יותר של המחיצה /data
.
תמונות מצב וירטואליות A/B דחוסות מבוססות על הרכיבים הבאים שזמינים ב-Android מגרסה 12 ואילך:
dm-user
, מודול ליבה (kernel) שדומה ל-FUSE שמאפשר מרחב משתמשים כדי להטמיע התקני בלוקים.snapuserd
, דימון (daemon) במרחב המשתמשים כדי להטמיע תמונת מצב חדשה הפורמט.
הרכיבים האלה מפעילים את הדחיסה. השינויים הנדרשים האחרים בוצעו ב להטמיע את היכולות של תמונות המצב הדחוסות שמפורטות בקטעים הבאים: פורמט COW לקובצי מצב דחוסים, dm-user ו-Snapuserd.
פורמט COW לקובצי מצב דחוסים
ב-Android מגרסה 12 ואילך, תמונות מצב דחוסות משתמשות ב פורמט COW. דומה לפורמט המובנה של הליבה, שמשמש לפעולות לא דחוסות תמונות מצב, לפורמט COW עבור תמונות המצב הדחוסות יש קטעים מתחלפים מטא-נתונים ונתונים. מטא-נתונים של הפורמט המקורי מותרים רק לצורך החלפה פעולות: החלפת בלוק X בתמונת הבסיס בתוכן של בלוק Y בתמונת המצב. הפורמט COW של תמונות המצב הדחוסים יותר אקספרסיבי תומכת בפעולות הבאות:
- העתקה: צריך להחליף את הבלוק X במכשיר הבסיסי בבלוק Y, במכשיר הבסיסי.
- החלפה: צריך להחליף את הבלוק X במכשיר הבסיסי בתוכן. של בלוק Y בתמונת המצב. כל אחד מהבלוקים האלה דחוס ב-gz.
- אפס: צריך להחליף את הבלוק X במכשיר הבסיסי בכל האפסים.
- XOR: מכשיר COW מאחסן בייטים דחוסים של XOR בין הבלוק X בלוק Y. (התכונה זמינה ב-Android מגרסה 13 ואילך).
עדכוני OTA מלאים כוללים רק פעולות של החלפה ואפס. מצטבר עדכוני OTA יכולים לכלול גם פעולות העתקה.
dm-user ב-Android 12
מודול הליבה של ה-Dm-user מאפשר ל-userspace
להטמיע בלוק של מיפוי מכשירים
מכשירים. רשומה בטבלה של משתמשי dm יוצרת מכשיר שונה תחת
/dev/dm-user/<control-name>
תהליך של userspace
יכול לדגום את המכשיר
לקבל בקשות קריאה וכתיבה מהליבה. לכל בקשה יש
מאגר נתונים זמני למרחב המשתמשים כדי לאכלס (לקריאה) או להפיץ (לצורך כתיבה).
מודול הליבה dm-user
מספק ממשק ליבה (kernel) חדש שגלוי למשתמש
שלא חלק מבסיס הקוד של kernel.org ב-upstream. עד אז, Google
שומרת לעצמה את הזכות לשנות את הממשק של dm-user
ב-Android.
Snapuserd
רכיב מרחב המשתמשים snapuserd
ב-dm-user
מיישם A/B וירטואלי
דחיסה.
בגרסה הלא דחוסה של Virtual A/B (ב-Android 11 ומטה, או
ב-Android 12 בלי האפשרות 'תמונת מצב דחוסה')
המכשיר COW הוא קובץ גולמי. כאשר דחיסה מופעלת, פונקציות COW
במקום זאת כמכשיר dm-user
, שמחובר למופע של
דימון (snapuserd
).
הליבה לא משתמשת בפורמט החדש COW. אז הרכיב snapuserd
מתרגמת בקשות בין פורמט Android COW לבין פורמט הליבה
פורמט:
איור 3. תרשים זרימה של Snapuserd כמתרגם בין Android ל-Kernel פורמטים של COW
התרגום והביטול דחיסה האלה אף פעם לא מתרחשים בדיסק. snapuserd
שמיירט את פעולות הקריאה והכתיבה של COW שמתרחשות בליבה (kernel),
שמטמיעה אותן בפורמט Android COW.
דחיסת XOR
במכשירים שמושקים עם Android מגרסה 13 ואילך, תכונת הדחיסה של XOR, שמופעלת כברירת מחדל, מפעילה מרחב משתמשים קובצי snapshot כדי לאחסן XOR בייטים דחוסים בין בלוקים ישנים לבלוקים חדשים. מתי רק מעט בייטים בבלוק משתנים בעדכון A/B וירטואלי, ה-XOR סכימת אחסון דחיסה משתמשת בפחות מקום מסכימת האחסון המוגדרת כברירת מחדל כי קובצי snapshot לא נשמרים באיכות 4,000 בייטים מלאים. ההקטנה הזו של תמונת המצב היא אפשרית כי נתוני XOR מכילים הרבה אפסים, וקל יותר לדחוס אותם מאשר נתונים גולמיים. חסימת נתונים. במכשירי Pixel, דחיסת XOR מקטינה את תמונת המצב ב-25% ל- 40%
במכשירים שמשדרגים ל-Android 13 ואילך, XOR צריך להפעיל דחיסה. לפרטים נוספים, ראו XOR דחיסת נתונים.
תהליכי דחיסת נתונים וירטואליים של A/B
בקטע הזה מופיעים פרטים על תהליך הדחיסה מסוג A/B וירטואלי שבו משתמשים Android 13 ו-Android 12.
קריאת מטא-נתונים (Android 12)
מטא-נתונים בנויים באמצעות דימון (daemon) מסוג snapuserd
. המטא-נתונים הם בעיקר
מיפוי של שני מזהים, כש-8 בייט כל אחד מהם, שמייצגים את המגזרים שרוצים למזג.
בdm-snapshot
השם נקרא disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
כאשר מקטע נתונים ישן מוחלף במקטע נתונים חדש, המערכת משתמשת בחריגת דיסק.
דימון (daemon) של snapuserd
קורא את קובץ ה-COW הפנימי דרך הספרייה של COW,
בונה את המטא-נתונים לכל אחת מפעולות COW שקיימות בקובץ COW.
קריאות מטא-נתונים מבוצעות מ-dm-snapshot
בליבה (kernel) בזמן יצירת המכשיר dm-
snapshot
.
האיור הבא מספק דיאגרמת רצף לנתיב ה-IO של המטא-נתונים עבודות בדרך.
איור 4. תהליך רצף לנתיב ה-IO בבניית מטא-נתונים
מיזוג (Android 12)
לאחר שתהליך האתחול הושלם, מנוע העדכון מסמן את החריץ כאתחול
מצליח ויוזם את המיזוג על ידי שינוי היעד dm-snapshot
יעד dm-snapshot-merge
.
dm-snapshot
עובר דרך המטא-נתונים ומבצע IO של מיזוג לכל דיסק
חריג. למטה מוצגת סקירה כללית ברמה גבוהה של נתיב ה-IO של המיזוג.
איור 5. סקירה כללית של נתיב ה-IO של המיזוג
אם המכשיר יופעל מחדש במהלך תהליך המיזוג, המיזוג ימשיך לאחר ההפעלה מחדש, והמיזוג יושלם.
יצירת שכבות של מיפוי מכשירים
במכשירים שמושקים עם Android מגרסה 13 ואילך,
בדחיסת A/B מתבצעות תהליכי מיזוג תמונות מצב ותמונת מצב בדחיסת נתוני A/B
מיוצג על ידי רכיב מרחב המשתמשים snapuserd
. במכשירים שמשדרגים ל-Android
מגיל 13 ומעלה, צריך להפעיל את התכונה הזו. עבור
לפרטים, ראו מרחב משתמשים
ממזגים.
בהמשך מתואר תהליך הדחיסה של Virtual A/B:
- ה-framework טוען את המחיצה
/system
אל מכשירdm-verity
, שמונחים בערימה על מכשירdm-user
. כלומר, בכל קלט/פלט (I/O) ממערכת הקבצים הבסיסית מנותבת אלdm-user
. dm-user
מנתב את הקלט/פלט אל מרחב המשתמשיםsnapuserd
daemon, שמטפל של הבקשה לקלט/פלט (I/O).- כשפעולת המיזוג מסתיימת, ה-framework מתכווץ של
dm-verity
ב- העליון שלdm-linear
(system_base
) ומסיר אתdm-user
.
איור 6. תהליך דחיסת נתונים וירטואלי A/B
אפשר להפסיק את תהליך המיזוג של תמונות המצב. אם המכשיר יופעל מחדש במהלך תהליך המיזוג, תהליך המיזוג ימשיך לאחר אתחול מחדש.
התחלת מעברים
במהלך הפעלה עם קובצי snapshot דחוסים, השלב הראשון חייב להתחיל
snapuserd
כדי לטעון מחיצות. יש בעיה: כשטוענים את sepolicy
ומתבצעת אכיפה, המדיניות snapuserd
מועברת להקשר שגוי ובקשות הקריאה שלו
נכשלים עם הכחשה של סלינוקס.
כדי לפתור את הבעיה, snapuserd
מועבר בשלב הנעילה עם init
, באופן הבא:
- שלב ראשון
init
מפעיל אתsnapuserd
מ-Rramdisk ושומר חלון פתוח ומתאר קובץ במשתנה סביבה. - בשלב הראשון
init
מעביר את מערכת הקבצים הבסיסית למחיצת המערכת, ואז מפעיל את עותק המערכת שלinit
. - עותק המערכת של
init
קורא את המדיניות המשולבת במחרוזת. Init
מפעיל אתmlock()
בכל הדפים שמגובים ב-ext4. לאחר מכן המערכת משביתה את כל הפריטים טבלאות מיפוי מכשירים לקובצי snapshot, ועוצרsnapuserd
. לאחר מכן אסור לקרוא ממחיצות, מפני שפעולה זו גורמת לקיבוע.- שימוש במתאר פתוח בעותק של Radisk של
snapuserd
,init
הפעלה מחדש של הדימון עם ההקשר הנכון של סלינוקס. טבלאות של מיפוי מכשירים עבור מכשירים בתמונת מצב יופעלו מחדש. - הפעלה מפעילה
munlockall()
– אפשר לבצע שוב הזמנת נתונים (IO)
שימוש במרחב המשותף
בטבלה הבאה מוצגת השוואה של נפח האחסון בין יעדי OTA שונים מנגנונים על סמך גדלי מערכת ההפעלה ו-OTA של Pixel.
השפעת הגודל | שאינו A/B | בדיקת A/B | בדיקת A/B וירטואלית | בדיקת A/B וירטואלית (דחוסה) |
---|---|---|---|---|
תמונת היצרן המקורית | 4.5GB Super (תמונת 3.8G + 700 מיליון שמורים)1 | 9GB Super (3.8G + 700M שמורים, לשני משבצות) | 4.5GB Super (תמונת 3.8G + 700 מיליון מקומות שמורים) | 4.5GB Super (תמונת 3.8G + 700 מיליון מקומות שמורים) |
מחיצות סטטיות אחרות | /cache | ללא | ללא | ללא |
נפח אחסון נוסף במהלך OTA (שטח שהוחזר לאחר החלת OTA) | 1.4GB ב-/data | 0 | 3.8GB 2 ב-/data | 2.1GB 2 ב-/data |
נפח האחסון הכולל שנדרש כדי להחיל OTA | 5.9GB 3 (סופר-נתונים ונתונים) | 9GB (מעולה) | 8.3GB 3 (סופר-נתונים ונתונים) | 6.6GB 3 (סופר-נתונים ונתונים) |
1מציינת פריסה משוערת, על סמך מיפוי של Pixel.
2בהנחה שתמונת המערכת החדשה זהה לגודל המקורי.
3דרישת הרווח היא זמנית עד להפעלה מחדש.
כדי להטמיע A/B וירטואלי או להשתמש ביכולות של קובץ snapshot דחוס, הטמעת A/B וירטואלי