העברת FUSE

Android 12 תומך בחיבור FUSE, שמצמצם את תקורת ה-FUSE כדי להשיג ביצועים דומים לביצועים של גישה ישירה למערכת הקבצים הנמוכה יותר. התכונה FUSE passthrough נתמכת בליבות android12-5.4,‏ android12-5.10 ו-android-mainline (בדיקה בלבד). כלומר, התמיכה בתכונה הזו תלויה בליבה שבה המכשיר משתמש ובגרסת Android שפועלת במכשיר:

  • מכשירים שעוברים שדרוג מ-Android 11 ל-Android 12 לא יכולים לתמוך ב-FUSE passthrough כי הליבות של המכשירים האלה קפואות, והן לא יכולות לעבור לליבה ששודרגה באופן רשמי עם השינויים של FUSE passthrough.

  • במכשירים שיושקו עם Android 12 תהיה תמיכה ב-FUSE passthrough כשמשתמשים בליבה רשמית. במכשירים כאלה, קוד המסגרת של Android שמטמיע העברה ישירה (passthrough) של FUSE מוטמע במודול הראשי MediaProvider, שמשודרג באופן אוטומטי. גם במכשירים שלא מטמיעים את MediaProvider כמודול ראשי (למשל, מכשירי Android Go), יש גישה לשינויים ב-MediaProvider כי הם משותפים באופן ציבורי.

FUSE לעומת SDCardFS

מערכת קבצים במרחב המשתמש (FUSE) היא מנגנון שמאפשר לליבה (מנהל ההתקן של FUSE) להעביר למיקור חוץ פעולות שמבוצעות במערכת קבצים של FUSE, לתוכנית במרחב המשתמש (דימון FUSE) שמטמיעה את הפעולות. מערכת Android 11 הוציאה משימוש את SDCardFS והפך את FUSE לפתרון ברירת המחדל לאמולציית אחסון. כחלק מהשינוי הזה, מערכת Android הטמיעה את דימון (daemon) שלה כדי ליירט גישה לקבצים, לאכוף תכונות נוספות של אבטחה ופרטיות, ולבצע שינויים בקבצים בזמן הריצה.

FUSE הנסיגות האלה נגרמות בגלל שרשרת של רכיבים שמשתפים פעולה בהטמעה של מערכת הקבצים FUSE, וגם בגלל מספר מעברים ממרחב הליבה למרחב המשתמש בתקשורת בין מנהל ה-FUSE לבין הדימון של FUSE (לעומת גישה ישירה למערכת הקבצים התחתונה, שהיא יעילה יותר ומוטמעת באופן מלא בליבה).

כדי לצמצם את הנסיגות האלה, אפליקציות יכולות להשתמש בהצמדה כדי לצמצם את העתקת הנתונים, ולהשתמש ב-ContentProvider API כדי לקבל גישה ישירה לקבצים ברמה נמוכה יותר של מערכת הקבצים. גם עם השיפורים האלה ושיפורים אחרים, יכול להיות שרוחב הפס של פעולות קריאה וכתיבה יהיה קטן יותר כשמשתמשים ב-FUSE בהשוואה לגישה ישירה למערכת הקבצים ברמה הנמוכה יותר  – במיוחד בפעולות קריאה אקראיות, שבהן לא ניתן להיעזר במטמון או בקריאה מראש. בנוסף, אפליקציות שמקבלות גישה ישירה לאחסון דרך הנתיב הקודם /sdcard/ ממשיכות להראות ירידה משמעותית בביצועים, במיוחד כשהן מבצעות פעולות עם עומס גבוה על קלט/פלט.

בקשות של מרחב המשתמש של SDcardFS

השימוש ב-SDcardFS יכול להאיץ את הדמיית האחסון ובדיקות ההרשאות של FUSE על ידי הסרת הקריאה של מרחב המשתמש מהליבה. בקשות במרחב המשתמש עוברות את הנתיב: מרחב המשתמש → VFS‏ → sdcardfs‏ → VFS‏ → ext4‏ → מטמון דפים/אחסון.

FUSE Passthrough SDcardFS

איור 1. בקשות למרחב המשתמשים של SDcardFS

בקשות של מרחב המשתמש של FUSE

בהתחלה, FUSE שימש להפעלת אמולציית אחסון ולאפשרות לאפליקציות להשתמש באופן שקוף באחסון הפנימי או בכרטיס SD חיצוני. השימוש ב-FUSE גורם לקצת זמן אחזור מיותר, כי כל בקשה במרחב המשתמש עוברת את הנתיב: מרחב המשתמש → VFS‏ (מערכת קבצים מנוהלת) → מנהל ההתקן של FUSE‏ (FUSE driver) → דימון FUSE‏ (FUSE daemon) → VFS‏ (מערכת קבצים מנוהלת) → ext4‏ (אחסון/מטמון דפים).

FUSE Passthrough FUSE

איור 2. בקשות של מרחב המשתמש של FUSE

בקשות להפעלת FUSE

רוב הרשאות הגישה לקובץ נבדקות בזמן פתיחת הקובץ, ובדיקות נוספות של ההרשאות מתבצעות בזמן קריאה מהקובץ ובזמן כתיבת הקובץ. במקרים מסוימים, אפשר לדעת בזמן פתיחת הקובץ שללא צורך להעביר את הבקשות לקריאה ולכתיבה מהדריבר של FUSE ל-daemon של FUSE (כי הפעולה הזו רק מעבירה נתונים ממקום אחד למקום אחר).

כשמשתמשים ב-FUSE passthrough, הדימון של FUSE שמטפל בבקשה פתוחה יכול להודיע למנהל ההתקן של FUSE שהפעולה מותרת ושאפשר להעביר ישירות למערכת הקבצים התחתונה את כל הבקשות הבאות לקריאה ולכתיבה. כך אפשר להימנע מהעלות הנוספת של ההמתנה לדימון FUSE במרחב המשתמש כדי להשיב לבקשות של מנהל ההתקן FUSE.

בהמשך מוצגת השוואה בין בקשות העברה של FUSE ושל FUSE.

השוואה בין FUSE Passthrough

איור 3. בקשת FUSE לעומת בקשת העברה של FUSE

כשאפליקציה מבצעת גישה למערכת קבצים של FUSE, מתבצעות הפעולות הבאות:

  1. מנהל ההתקן של FUSE מטפל בבקשה ומוסיף אותה לתור, ואז מעביר אותה לדימון FUSE שמטפל במערכת הקבצים של FUSE דרך מופע חיבור ספציפי בקובץ /dev/fuse, שקריאה שלו חסומה לדימון FUSE.

  2. כשהדימון (daemon) של FUSE מקבל בקשה לפתיחת קובץ, הוא מחליט אם העברת הנתונים של FUSE תהיה זמינה עבור הקובץ הספציפי הזה. אם הוא זמין, הדימון:

    1. שליחת הודעה לנהג FUSE על הבקשה הזו.

    2. הפעלת העברה של FUSE לקובץ באמצעות FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl, שצריך לבצע על מתאר הקובץ של /dev/fuse שנפתח.

  3. הפונקציה ioctl מקבלת (כפרמטר) מבנה נתונים שמכיל את הפרטים הבאים:

    • מתאר הקובץ של הקובץ התחתון של מערכת הקבצים שמשמש כיעד לתכונת המעבר.

    • המזהה הייחודי של בקשת ה-FUSE שמטופלת כרגע (חייבת להיות פתוחה או שנוצרה ונפתחה).

    • שדות נוספים שאפשר להשאיר ריקים, והם מיועדים להטמעות עתידיות.

  4. אם ה-ioctl מצליח, הדימון (daemon) של FUSE משלים את הבקשה הפתוחה, מנהל התקן FUSE מטפל בתשובת דימון (daemon) של FUSE, והפניה לקובץ התחתון של מערכת הקבצים מתווספת לקובץ FUSE שבתוך הליבה. כשאפליקציה מבקשת לבצע פעולת קריאה/כתיבה בקובץ FUSE, מנהל ההתקן של FUSE בודק אם ההפניה לקובץ במערכת קבצים ברמה נמוכה יותר זמינה.

    • אם יש קובץ עזר, מנהל ההתקן יוצר בקשה חדשה למערכת קבצים וירטואלית (VFS) עם אותם פרמטרים שמטרגטים את הקובץ של מערכת הקבצים הנמוכה יותר.

    • אם אין הפניה זמינה, הנהג מעביר את הבקשה לדימון (daemon) של FUSE.

הפעולות שלמעלה מתרחשות לקריאה/כתיבה ולקריאה-iter/כתיבה-iter בקבצים כלליים, ולפעולות קריאה/כתיבה בקבצים שממופים לזיכרון. העברת אותות מסוג FUSE לקובץ נתון קיימת עד שהקובץ הזה נסגר.

הטמעת העברה דרך FUSE

כדי להפעיל העברה (passthrough) של FUSE במכשירים עם Android 12, מוסיפים את השורות הבאות לקובץ $ANDROID_BUILD_TOP/device/…/device.mk של מכשיר היעד.

# Use FUSE passthrough
PRODUCT_PRODUCT_PROPERTIES += \
    persist.sys.fuse.passthrough.enable=true

כדי להשבית את העברת הנתונים ב-FUSE, צריך להשמיט את שינוי ההגדרה שלמעלה או להגדיר את persist.sys.fuse.passthrough.enable לערך false. אם הפעלתם בעבר את העברת הנתונים של FUSE, השבתה שלו תמנע מהמכשיר להשתמש בהעברת הנתונים של FUSE, אבל המכשיר ימשיך לפעול.

כדי להפעיל או להשבית את העברת הנתונים של FUSE בלי להפעיל את המכשיר, משנים את מאפיין המערכת באמצעות פקודות ADB. למטה מוצגת דוגמה.

adb root
adb shell setprop persist.sys.fuse.passthrough.enable {true,false}
adb reboot

לקבלת עזרה נוספת, אפשר לעיין בהטמעת העזרה.

אימות העברה של FUSE

כדי לוודא ש-MediaProvider משתמש בחיבור FUSE, בודקים אם יש ב-logcat הודעות לניפוי באגים. לדוגמה:

adb logcat FuseDaemon:V \*:S
--------- beginning of main
03-02 12:09:57.833  3499  3773 I FuseDaemon: Using FUSE passthrough
03-02 12:09:57.833  3499  3773 I FuseDaemon: Starting fuse...

הרשומה FuseDaemon: Using FUSE passthrough ביומן מוודאת שנעשה שימוש ב-FUSE passthrough.

בדיקת ה-CTS של Android 12 כוללת את CtsStorageTest, שכוללת בדיקות שמפעילות העברה ישירה (passthrough) של FUSE. כדי להריץ את הבדיקה באופן ידני, צריך להשתמש באימות כפי שמוצג בהמשך:

atest CtsStorageTest