การเกิดว่างเปล่าเมื่อ ext4


83

ฉันเพิ่งอ่านข้อมูลในBirthส่วนของstatและปรากฏ ext4 ควรสนับสนุน แต่แม้ไฟล์ที่ฉันเพิ่งสร้างมันว่างเปล่า

 ~  % touch test                                                       slave-iv
 ~  % stat test.pl                                                     slave-iv
  File: ‘test.pl’
  Size: 173             Blocks: 8          IO Block: 4096   regular file
Device: 903h/2307d      Inode: 41943086    Links: 1
Access: (0600/-rw-------)  Uid: ( 1000/xenoterracide)   Gid: (  100/   users)
Access: 2012-09-22 18:22:16.924634497 -0500
Modify: 2012-09-22 18:22:16.924634497 -0500
Change: 2012-09-22 18:22:16.947967935 -0500
 Birth: -

 ~  % sudo tune2fs -l /dev/md3 | psp4                                  slave-iv
tune2fs 1.42.5 (29-Jul-2012)
Filesystem volume name:   home
Last mounted on:          /home
Filesystem UUID:          ab2e39fb-acdd-416a-9e10-b501498056de
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    journal_data
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              59736064
Block count:              238920960
Reserved block count:     11946048
Free blocks:              34486248
Free inodes:              59610013
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      967
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
RAID stride:              128
RAID stripe width:        256
Flex block group size:    16
Filesystem created:       Mon May 31 20:36:30 2010
Last mount time:          Sat Oct  6 11:01:01 2012
Last write time:          Sat Oct  6 11:01:01 2012
Mount count:              14
Maximum mount count:      34
Last checked:             Tue Jul 10 08:26:37 2012
Check interval:           15552000 (6 months)
Next check after:         Sun Jan  6 07:26:37 2013
Lifetime writes:          7255 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
First orphan inode:       55313243
Default directory hash:   half_md4
Directory Hash Seed:      442c66e8-8b67-4a8c-92a6-2e2d0c220044
Journal backup:           inode blocks

เหตุใดext4พาร์ติชันของฉันจึงไม่เติมข้อมูลในฟิลด์นี้

คำตอบ:


93

ฟิลด์ได้รับการเติมข้อมูล (ดูด้านล่าง) เท่านั้นcoreutils statไม่แสดง เห็นได้ชัดว่าพวกเขากำลังรอ1สำหรับอินเตอร์เฟซxstat()

coreutils patches - aug. 2012 - สิ่งที่ต้องทำ

สนับสนุนสถิติ (1) และ ls (1) สำหรับเวลาเกิด ขึ้นอยู่กับ xstat () ถูกจัดเตรียมโดยเคอร์เนล

คุณสามารถรับเวลาสร้างผ่านdebugfs:

debugfs -R 'stat <inode_number>' DEVICE

เช่นสำหรับฉัน/etc/profileที่เปิดอยู่/dev/sda2(ดูวิธีการค้นหาไฟล์ที่อุปกรณ์เปิดอยู่ ):

สถิติ -c% i / etc / profile
398264
debugfs -R 'stat <398264>' /dev/sda2
debugfs 1.42.5 (29-Jul-2012)
Inode: 398264   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2058737571    Version: 0x00000000:00000001
User:     0   Group:     0   Size: 562
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
 atime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
 mtime: 0x506b860b:19fa3c34 -- Wed Oct  3 02:25:47 2012
crtime: 0x50476677:dcd84978 -- Wed Sep  5 16:49:27 2012
Size of extra inode fields: 28
EXTENTS:
(0):3308774

1 Linus 'ตอบกลับหัวข้อ LKML


7
@Sparhawk: ฉันมีปัญหานี้ด้วยไฟล์/home/user/path/to/fileเพราะ/homeอยู่ในพาร์ทิชันที่แยกต่างหาก ในกรณีที่เส้นทางที่ให้ไว้เพื่อจะต้องเทียบกับstat /homeตัวอย่าง: sudo debugfs -R 'stat user/path/to/file' /dev/sda2. เพื่อกำจัดการจัดการเส้นทางเราสามารถให้statหมายเลขไอโหนดแทนเส้นทาง:sudo debugfs -R "stat <$(stat -c %i /home/user/path/to/file)>" /dev/sda5
jpfleury

3
สามารถใช้เพื่อรับเวลาสร้างไฟล์จากระบบไฟล์ที่ติดตั้งบนเครือข่ายได้หรือไม่
taranaki

1
ดังนั้นนี่ไม่ใช่การประทับเวลาที่เหนือกว่าการสร้างระบบไฟล์ หมายความว่าหากไฟล์ถูกสร้างขึ้นเมื่อ 25 ปีที่แล้วและคัดลอกผ่านระบบฟิสิคัลหรือเมานต์ที่แตกต่างกันจำนวนมากไม่มีวิธีใดที่จะสามารถค้นหาข้อมูลวันที่สร้างในเมทาดาทาใด ๆ ได้? ดังนั้นวิธีเดียวที่จะรู้ว่าเมื่อไฟล์ถูกสร้างคือการพิมพ์ลงในชื่อไฟล์? หรือภายในเนื้อหา มีเหตุผลใดบ้างที่ทำให้เกิดการใช้งานที่ไม่แปลกประหลาดนี้?
sinekonata

2
เมตาดาต้าไฟล์ @sinekonata เป็นระบบมากขึ้น (เป็นคำตอบนี้แสดงให้เห็นชั้นของระบบปฏิบัติการทุกคนต้องสามารถดำเนินการได้) และทำให้มันข้ามสำเนาระหว่างเครื่องอาศัยการสนับสนุนสำหรับรูปแบบเมตาดาต้าว่าโดยทั้งสองระบบและเครื่องมือการคัดลอก สิ่งนี้หมายความว่าอะไร: คุณโชคดีถ้าคุณได้รับชื่อไฟล์ที่ไม่ถูกจัดการ อีกทางเลือกหนึ่งรูปแบบไฟล์บางประเภทอนุญาตให้คุณแทรกข้อมูลเมตาภายในไฟล์ (เช่นID3 ) และโดยทั่วไปใช้งานได้ดี แต่หลายรูปแบบไม่มีคุณสมบัติดังกล่าว ในที่สุดคุณสามารถวางไฟล์ไว้ในไฟล์เก็บถาวรเช่น
AndréParamés

1
โปรดทราบว่าจำเป็นต้องใช้<และ>รอบหมายเลขไอโหนด พวกเขามักจะใช้ในตัวอย่างเพื่อล้อมรอบตัวแปรที่ควรปรับ แต่ในกรณีนี้พวกเขาจะต้องป้อนอย่างแท้จริง หากไม่มีหมายเลขไอดีจะถือว่าเป็นเส้นทางและคุณได้รับFile not found by ext2_lookupข้อผิดพลาด
mivk

31

ฉันรวมสิ่งนี้เป็นฟังก์ชั่นเปลือกอย่างง่าย:

get_crtime() {
  for target in "${@}"; do
    inode=$(stat -c %i "${target}")
    fs=$(df  --output=source "${target}"  | tail -1)
    crtime=$(sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null | 
    grep -oP 'crtime.*--\s*\K.*')
    printf "%s\t%s\n" "${target}" "${crtime}"
  done
    }

จากนั้นคุณสามารถเรียกใช้ด้วย

$ get_crtime foo foo/file /etc/
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014
/etc/   Wed Aug  1 20:42:03 2012

22

xstatฟังก์ชั่นไม่เคยได้ผสานเข้าฉีด อย่างไรก็ตามใหม่statxโทรถูกเสนอในภายหลังและได้รับการรวมอยู่ในลินุกซ์ 4.11 การstatx(2)เรียกระบบใหม่จะรวมเวลาสร้างในโครงสร้างการส่งคืน เสื้อคลุมสำหรับstatx(2)ถูกบันทึกอยู่ใน glibc เฉพาะใน2.28 (ปล่อยสิงหาคม 2018) และการสนับสนุนสำหรับการใช้ wrapper นี้ถูกเพิ่มเข้ามาในGNU coreutils 8.31 (เปิดตัวมีนาคม 2019):

ตอนนี้ stat พิมพ์เวลาการสร้างไฟล์เมื่อระบบไฟล์รองรับบนระบบ GNU Linux ที่มี glibc> = 2.28 และเคอร์เนล> = 4.11

% stat --version
stat (GNU coreutils) 8.31
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Michael Meskes.
% stat /
  File: /
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: b302h/45826d    Inode: 2           Links: 17
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-06-06 20:03:12.898725626 +0900
Modify: 2019-05-28 05:15:44.452651395 +0900
Change: 2019-05-28 05:15:44.452651395 +0900
 Birth: 2018-06-07 20:35:54.000000000 +0900

สิ่งต่อไปนี้คือตัวอย่างstatxที่ผู้ใช้ยังไม่ทันติดตาม (glibc หรือ coreutils ที่เก่ากว่า) ไม่ใช่เรื่องง่ายที่จะเรียกการโทรของระบบโดยตรงในโปรแกรม C โดยทั่วไป glibc จะให้ wrapper ที่ทำให้งานง่ายขึ้น แต่โชคดีที่ @whotwagner เขียนตัวอย่างโปรแกรม Cที่แสดงวิธีใช้การstatx(2)เรียกระบบบนระบบ x86 และ x86-64 เอาท์พุทมันเป็นรูปแบบเดียวกับstatค่าเริ่มต้นโดยไม่มีตัวเลือกการจัดรูปแบบใด ๆ แต่มันง่ายในการปรับเปลี่ยนเพื่อพิมพ์เพียงเวลาเกิด (หากคุณมี glibc เพียงพอใหม่คุณจะไม่ต้องการสิ่งนี้ - คุณสามารถใช้statxโดยตรงตามที่อธิบายไว้ในman 2 statx)

ก่อนอื่นโคลนมัน:

git clone https://github.com/whotwagner/statx-fun

คุณสามารถรวบรวมstatx.cรหัสหรือถ้าคุณต้องการเวลาเกิดให้สร้างbirth.cไดเรกทอรีในโคลนด้วยรหัสต่อไปนี้ (ซึ่งเป็นรุ่นที่น้อยที่สุดของstatx.cการพิมพ์เพียงแค่การประทับเวลาการสร้างรวมถึงความแม่นยำระดับนาโนวินาที):

#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>

// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>

/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif

#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))

int main(int argc, char *argv[])
{
    int dirfd = AT_FDCWD;
    int flags = AT_SYMLINK_NOFOLLOW;
    unsigned int mask = STATX_ALL;
    struct statx stxbuf;
    long ret = 0;

    int opt = 0;

    while(( opt = getopt(argc, argv, "alfd")) != -1)
    {
        switch(opt) {
            case 'a':
                flags |= AT_NO_AUTOMOUNT;
                break;
            case 'l':
                flags &= ~AT_SYMLINK_NOFOLLOW;
                break;
            case 'f':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_FORCE_SYNC;
                break;
            case 'd':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_DONT_SYNC;
                break;
            default:
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (optind >= argc) {
        exit(EXIT_FAILURE);
    }

    for (; optind < argc; optind++) {
        memset(&stxbuf, 0xbf, sizeof(stxbuf));
        ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
        if( ret < 0)
        {
            perror("statx");
            return EXIT_FAILURE;
        }
        printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
    }
    return EXIT_SUCCESS;
}

แล้ว:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

ในทางทฤษฎีสิ่งนี้ควรทำให้เวลาในการสร้างสามารถเข้าถึงได้ในระบบไฟล์มากกว่าระบบ ext * ( debugfsเป็นเครื่องมือสำหรับระบบไฟล์ ext2 / 3/4 และไม่สามารถใช้กับผู้อื่นได้) มันทำงานได้กับระบบ XFS แต่ไม่ใช่สำหรับ NTFS และ exfat ฉันเดาว่าระบบไฟล์ของ FUSE สำหรับผู้ที่ไม่มีเวลาสร้าง


5

มีกรณีที่เวลาเกิดจะว่างเปล่าอื่น / ศูนย์ / ประ: Ext4 ขนาด Inode จะต้องมีอย่างน้อย 256bytes crtimeในการจัดเก็บ ปัญหาเกิดขึ้นหากคุณเริ่มสร้างระบบไฟล์ที่มีขนาดเล็กกว่า 512MB (ขนาดของไอโหนดเริ่มต้นจะเป็น 128 ไบต์ดู/etc/mke2fs.confและmkfs.ext4manpage)

stat -c '%n: %w' testfile
testfile: -  

และ / หรือ

stat -c '%n: %W' testfile
testfile: 0

ตอนนี้ตรวจสอบระบบไฟล์ inode (มันใหญ่พอที่จะเก็บcrtime?):

tune2fs -l $(df . --output=source | grep ^/) | grep "Inode size:"
Inode size:           128

ข้อมูลทางเทคนิค: ในหน้าExt4 Disk Layoutโปรดทราบว่าคุณลักษณะบางอย่างของตาราง inode นั้นมีขนาดเกิน 0x80 (128)


ถูกต้อง (ฉันจำได้ว่าอ่านเกี่ยวกับเรื่องนี้ในvger ) ขีด จำกัด 512MB ถูกกำหนดในmke2fs.cบรรทัดที่1275
don_crissti

2

สำหรับสิ่งที่คุ้มค่าฉันรู้สึกอวดดีดังนั้นเขียน bash wrapper รอบ ๆ stat เพื่อสนับสนุน crtime โดยใช้ debugfs เพื่อดึงมันออกมาจากระบบไฟล์ ext4 พื้นฐานหากมี ฉันหวังว่ามันจะแข็งแกร่ง หาได้ที่นี่

โปรดทราบว่าการแก้ไขนั้นปรากฏอยู่ในรายการสิ่งที่ต้องทำสำหรับ Linux ตามที่ระบุไว้ในสคริปต์นั้น ดังนั้นเสื้อคลุมตัวนี้มีอายุขัยเพียงเล็กน้อยเท่านั้นจนกว่าจะเสร็จสิ้นและเป็นการออกกำลังกายในสิ่งที่ทำได้


3
โปรดทราบว่าxstat()ในที่สุดก็มีการเพิ่มลงใน Linux ดังนั้นมันเป็นเพียงเรื่องของเวลาก่อน GNU libc และfindเพิ่มการสนับสนุนสำหรับมัน
Stéphane Chazelas

1
น่ากลัว! ข่าวดีแน่นอน
Bernd Wechner

6
ด้วยการขอโทษที่เป็นคนอวดรู้คุณดูเหมือนจะไม่เข้าใจความหมายของคำว่า "คนอวดดี"
Nick

"มีความกังวลมากเกินไปกับรายละเอียดนาทีหรือพิธีการ" - ในคำตอบที่ยอมรับนั้นใช้ได้ แต่ ... ลองทำมันให้เป็นระเบียบ ;-)
Bernd Wechner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.