לאנדרואיד יש שני מנגנוני עדכון: עדכוני A/B (ללא תפרים) ועדכונים שאינם A/B. כדי להפחית את מורכבות הקוד ולשפר את תהליך העדכון, באנדרואיד 11 שני המנגנונים מאוחדים באמצעות A/B וירטואלי כדי להביא עדכונים חלקים לכל המכשירים בעלות מזערית של אחסון. אנדרואיד 12 מציעה אפשרות של דחיסת A/B וירטואלית לדחיסת מחיצות מצולמות. גם באנדרואיד 11 וגם באנדרואיד 12 חלים הדברים הבאים:
- עדכוני A/B וירטואליים הם חלקים כמו עדכוני A/B. עדכוני A/B וירטואליים ממזערים את הזמן שבו מכשיר לא מקוון ואינו שמיש.
- ניתן להחזיר עדכוני A/B וירטואליים לאחור. אם מערכת ההפעלה החדשה לא מצליחה לאתחל, המכשירים חוזרים אוטומטית לגרסה הקודמת.
- עדכוני A/B וירטואליים משתמשים במינימום שטח נוסף על ידי שכפול רק המחיצות המשמשות את טוען האתחול. מחיצות אחרות הניתנות לעדכון מצולמות.
רקע ומינוח
סעיף זה מגדיר את הטרמינולוגיה ומתאר את הטכנולוגיה התומכת ב-A/B וירטואלי.
מיפוי התקנים
Device-mapper היא שכבת בלוק וירטואלית של לינוקס המשמשת לעתים קרובות באנדרואיד. עם מחיצות דינמיות , מחיצות כמו /system
הן ערימה של התקנים שכבות:
- בתחתית הערימה נמצאת מחיצת העל הפיזית (לדוגמה,
/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
dm-תצלום
Virtual A/B מסתמך על dm-snapshot
, מודול מיפוי התקן לצילום מצב של התקן אחסון. בעת שימוש dm-snapshot
, ישנם ארבעה מכשירים הפועלים:
- ההתקן הבסיסי הוא המכשיר שצולם. בדף זה, התקן הבסיס הוא תמיד מחיצה דינמית, כגון מערכת או ספק.
- התקן העתקה על כתיבה (COW), לרישום שינויים במכשיר הבסיס. זה יכול להיות בכל גודל, אבל זה חייב להיות גדול מספיק כדי להכיל את כל השינויים במכשיר הבסיס.
- התקן תמונת המצב נוצר באמצעות יעד
snapshot
. כתיבה למכשיר תמונת המצב נכתבת למכשיר COW. קורא מהתקן תמונת המצב קורא מהתקן הבסיס או התקן COW, תלוי אם הנתונים שאליהם הגישה השתנו על ידי תמונת המצב. - מכשיר המקור נוצר באמצעות יעד
snapshot-origin
. קורא למכשיר המקור הנקרא ישירות מהתקן הבסיס. כותב למכשיר המקור כותב ישירות למכשיר הבסיס, אך הנתונים המקוריים מגובים בכתיבה להתקן COW.
איור 2. מיפוי התקן עבור dm-snapshot
צילומי מצב דחוסים
ב-Android 12 ומעלה, מכיוון שדרישות השטח במחיצת /data
יכולות להיות גבוהות, אתה יכול לאפשר צילומי מצב דחוסים ב-build שלך כדי לתת מענה לדרישות השטח הגבוהות יותר של מחיצת /data
.
צילומי מצב דחוסים וירטואליים A/B בנויים על גבי הרכיבים הבאים הזמינים באנדרואיד 12 ואילך:
-
dm-user
, מודול ליבה דומה ל-FUSE המאפשר למרחב המשתמש ליישם התקני בלוק. -
snapuserd
, דמון מרחב משתמש ליישם פורמט חדש של תמונת מצב.
רכיבים אלו מאפשרים את הדחיסה. שאר השינויים ההכרחיים שנעשו כדי ליישם את יכולות צילומי המצב הדחוסים ניתנים בסעיפים הבאים: פורמט COW עבור צילומי מצב דחוסים , dm-user ו- Snapuserd .
פורמט COW עבור צילומי מצב דחוסים
ב-Android 12 ומעלה, צילומי מצב דחוסים משתמשים בפורמט COW. בדומה לפורמט המובנה של הליבה המשמש לצילומי מצב לא דחוסים, בפורמט COW עבור התמונות הדחוסות יש חלקים מתחלפים של מטא נתונים ונתונים. המטא נתונים של הפורמט המקורי מותרים רק עבור פעולות החלפה : החלף בלוק X בתמונת הבסיס בתוכן של בלוק Y בתמונת המצב. פורמט COW של צילומי מצב דחוסים יותר אקספרסיבי ותומך בפעולות הבאות:
- העתק : יש להחליף את בלוק X בהתקן הבסיס בבלוק Y בהתקן הבסיס.
- החלף : יש להחליף את בלוק X במכשיר הבסיס בתוכן של בלוק Y בתמונת המצב. כל אחד מהבלוקים האלה הוא gz דחוס.
- אפס : יש להחליף את בלוק X בהתקן הבסיס בכל האפסים.
- XOR : התקן COW מאחסן בתים דחוסים XOR בין בלוק X לבלוק Y. (זמין באנדרואיד 13 ומעלה.)
עדכוני OTA מלאים מורכבים מפעולות החלפה ואפס בלבד. עדכוני OTA מצטברים יכולים להיות בנוסף לפעולות העתקה .
dm-user באנדרואיד 12
מודול הקרנל dm-user מאפשר userspace
ליישם התקני בלוק-מיפוי התקנים. ערך טבלת dm-user יוצר התקן שונה תחת /dev/dm-user/<control-name>
. תהליך userspace
יכול לסקור את המכשיר כדי לקבל בקשות קריאה וכתיבה מהקרנל. לכל בקשה יש מאגר משויך שמרחב המשתמשים יוכל לאכלס (לקריאה) או להפיץ (לכתיבה).
מודול הקרנל dm-user
מספק ממשק חדש גלוי למשתמש לקרנל שאינו חלק מבסיס הקוד של kernel.org במעלה הזרם. עד שזה יקרה, גוגל שומרת לעצמה את הזכות לשנות את ממשק ה- dm-user
באנדרואיד.
snapuserd
רכיב מרחב המשתמש snapuserd
ל- dm-user
מיישם דחיסת A/B וירטואלית.
בגרסה הלא דחוסה של Virtual A/B, (או באנדרואיד 11 ומטה, או באנדרואיד 12 ללא אפשרות תמונת מצב דחוסה), מכשיר COW הוא קובץ גולמי. כאשר הדחיסה מופעלת, COW מתפקד במקום זאת כהתקן dm-user
, המחובר למופע של הדמון snapuserd
.
הקרנל אינו משתמש בפורמט COW החדש. אז רכיב snapuserd
מתרגם בקשות בין פורמט אנדרואיד COW לפורמט המובנה של הליבה:
איור 3. דיאגרמת זרימה של snapuserd כמתרגם בין פורמטים של אנדרואיד ו-Kernel COW
תרגום ופירוק זה לעולם לא מתרחשים בדיסק. רכיב snapuserd
מיירט את הקריאה והכתיבה של COW המתרחשות בליבה, ומיישם אותן באמצעות פורמט COW של Android.
דחיסת XOR
עבור מכשירים המופעלים עם אנדרואיד 13 ומעלה, תכונת הדחיסה של XOR, המופעלת כברירת מחדל, מאפשרת לצילומי מצב של מרחב המשתמש לאחסן בתים דחוסים של XOR בין בלוקים ישנים לבלוקים חדשים. כאשר רק כמה בתים בבלוק משתנים בעדכון וירטואלי A/B, ערכת אחסון הדחיסה של XOR משתמשת בפחות מקום מסכימת האחסון המוגדרת כברירת מחדל, מכיוון שתמונות מצב אינן מאחסנות בתים של 4K מלאים. הקטנה זו בגודל תמונת מצב אפשרי מכיוון שנתוני XOR מכילים אפסים רבים וקל יותר לדחוס מאשר נתוני בלוק גולמי. במכשירי Pixel, דחיסת XOR מפחיתה את גודל תמונת המצב ב-25% עד 40%.
עבור מכשירים שמשדרגים ל-Android 13 ומעלה, יש להפעיל דחיסת XOR. לפרטים, ראה דחיסת XOR .
תהליכי דחיסה וירטואליים A/B
סעיף זה מספק פרטים על תהליך דחיסת A/B וירטואלי בשימוש ב-Android 13 ו-Android 12.
קריאת מטא נתונים (אנדרואיד 12)
מטא נתונים נבנים על ידי דמון snapuserd
. המטא נתונים הם בעיקר מיפוי של שני מזהים, 8 בתים כל אחד, המייצגים את המגזרים שיש למזג. ב- dm-snapshot
זה נקרא disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
חריג של דיסק משמש כאשר נתח ישן של נתונים מוחלף בחדש.
דמון snapuserd
קורא את קובץ COW הפנימי דרך ספריית COW ובונה את המטא נתונים עבור כל אחת מפעולות COW הקיימות בקובץ COW.
קריאות מטא נתונים מופעלות מתמונת dm-snapshot
בליבה כאשר התקן dm- snapshot
נוצר.
האיור שלהלן מספק דיאגרמת רצף עבור נתיב ה-IO לבניית מטא נתונים.
איור 4. זרימת רצף עבור נתיב ה-IO בבניית מטא נתונים
מיזוג (אנדרואיד 12)
לאחר השלמת תהליך האתחול, מנוע העדכון מסמן את המשבצת כאתחול מוצלח ומתחיל את המיזוג על ידי החלפת יעד ה- dm-snapshot
למטרה dm-snapshot-merge
.
dm-snapshot
עובר על המטא-נתונים ומתחיל מיזוג IO עבור כל חריג דיסק. סקירה ברמה גבוהה של נתיב המיזוג IO מוצגת להלן.
איור 5. סקירה כללית של נתיב IO
אם המכשיר מופעל מחדש במהלך תהליך המיזוג, המיזוג יתחדש באתחול הבא, והמיזוג הושלם.
שכבות ממפה התקנים
עבור מכשירים המופעלים עם אנדרואיד 13 ומעלה, תהליכי המיזוג של תמונת מצב ותמונת מצב בדחיסת A/B וירטואלית מבוצעים על ידי רכיב מרחב המשתמש snapuserd
. עבור מכשירים המשדרגים ל-Android 13 ומעלה, תכונה זו חייבת להיות מופעלת. לפרטים, ראה מיזוג שטחי משתמש .
להלן מתאר תהליך דחיסת A/B וירטואלי:
- המסגרת מעלה את מחיצת
/system
מתוך התקןdm-verity
, אשר מוערם על גבי התקןdm-user
. המשמעות היא שכל קלט/פלט ממערכת קבצי השורש מנותב ל-dm-user
. -
dm-user
מנתב את ה-I/O ל-userspacesnapuserd
daemon, המטפל בבקשת ה-I/O. - כאשר פעולת המיזוג הושלמה, המסגרת ממוטטת
dm-verity
על גביdm-linear
(system_base
) ומסירה אתdm-user
.
איור 6. תהליך דחיסה וירטואלי A/B
תהליך מיזוג תמונת המצב יכול להיות מופרע. אם המכשיר מופעל מחדש במהלך תהליך המיזוג, תהליך המיזוג מתחדש לאחר אתחול מחדש.
פתח מעברים
בעת אתחול עם צילומי מצב דחוסים, ה-init בשלב הראשון חייב להתחיל snapuserd
כדי להעלות מחיצות. זה מציב בעיה: כאשר sepolicy
נטען ונאכפת, snapuserd
מוכנס בהקשר הלא נכון, ובקשות הקריאה שלו נכשלות, עם דחיות selinux.
כדי לטפל בזה, snapuserd
עובר בשלב נעילה עם init
, באופן הבא:
-
init
שלב ראשון מפעילsnapuserd
מה-ramdisk, ושומר לו מתאר קובץ פתוח במשתנה סביבה. -
init
שלב ראשון מעביר את מערכת הקבצים הבסיסית למחיצת המערכת, ואז מבצע את עותק המערכת שלinit
. - עותק המערכת של
init
קורא את המדיניות המשולבת למחרוזת. -
Init
מפעיל אתmlock()
בכל הדפים המגובים ב-ext4. לאחר מכן הוא משבית את כל טבלאות מיפוי המכשירים עבור התקני תמונת מצב, ומפסיקsnapuserd
. לאחר מכן חל איסור לקרוא ממחיצות, שכן פעולה זו גורמת למבוי סתום. - באמצעות המתאר הפתוח לעותק ramdisk של
snapuserd
,init
מפעיל מחדש את הדמון עם ההקשר הנכון של selinux. טבלאות מיפוי התקנים עבור התקני תמונת מצב מופעלות מחדש. - Init מפעיל את
munlockall()
- זה בטוח לבצע שוב IO.
שימוש בחלל
הטבלה הבאה מספקת השוואה של שימוש בשטח עבור מנגנוני OTA שונים תוך שימוש בגדלים של מערכת ההפעלה וה-OTA של Pixel.
גודל השפעה | לא A/B | א/ב | A/B וירטואלי | A/B וירטואלי (דחוס) |
---|---|---|---|---|
תמונת מפעל מקורית | 4.5GB סופר (תמונה 3.8G + 700M שמורות) 1 | סופר 9GB (3.8G + 700M שמורות, עבור שני חריצים) | 4.5GB סופר (תמונה 3.8G + 700M שמורות) | 4.5GB סופר (תמונה 3.8G + 700M שמורות) |
מחיצות סטטיות אחרות | /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 מציין פריסה משוערת המבוססת על מיפוי פיקסל.
2 מניח שתמונת מערכת חדשה זהה לגודל המקורי.
3 דרישת המקום היא חולפת עד לאתחול מחדש.
להטמעת A/B וירטואלית, או להשתמש ביכולות של תמונת מצב דחוסה, ראה הטמעת A/B וירטואלי