1 (12.02.2011 09:58:18 отредактировано Fat-Zer)

Не посоветуете, что почитать о разработке ФС вообще и под линукс в частности? В идеале было бы найти какую-нить статью, где во всех подробностях расписывается код кокой-нить ext2.

Сейчас читаю "Linux: азбука ядра" и "Linux device drivers".

И ещё посоветуйте какой-нить форум, где есть кернелхакеры, можно даже на языке потенциального противника, а то сдаётся мне, что вопросов у меня будет ещё много и они будут не совсем в тему данного сообщества.

95% процентов проблем находятся между клавиатурой и стулом.

2

здесь их очень много

ПатреГ не любит Gnome...

3

я вот не понимаю, что вам не почитать-бы код самой ext2? что непонятно - спрашивайте. например у меня. Кстати, к ядру это не имеет отношения. к девайсам тоже, дело в том, что ext2 можно развернуть где угодно - хоть на флешке, хоть на CDROM'е, хоть в любом другом файле.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

4

Термо, плюсануть хотел, но лениво bx

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

5

у меня отключено ибо нех!  ag

ПатреГ не любит Gnome...

6

прежде всего я не понимаю с чего начать разбираться... я плохо представляю какие части вынесены в vfs, как фс регистрируется в системе? что берёт на себя vfs, что драйверы блочных устройств, а что надо реализовывать в самом модуле ФС.

95% процентов проблем находятся между клавиатурой и стулом.

7

Fat-Zer пишет:

какие части вынесены в vfs

что значит v?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

8 (13.02.2011 11:13:44 отредактировано Fat-Zer)

drBatty пишет:

что значит v?

virtual  - абстракция, на уровень выше конкретных файловых систем... именно к ней, например, сначала поступают системные вызовы типа read(), write(), open() итп... если я не заблуждаюсь...

95% процентов проблем находятся между клавиатурой и стулом.

9

Начал потихоньку разбираться... думаю никто не будет против, если буду пользовать эту ветку для записи своих мыслей(а то в кащенко уж больно неудобный форум)... Если что - комментируйте/поправляйте smile

Итак функция инициализации:
fs/ext2/super.c  struct file_system_type ext2_fs_type;   init_ext2_fs(void)

+ открыть спойлер
static struct file_system_type ext2_fs_type = {
    .owner        = THIS_MODULE,
    .name        = "ext2",
    .get_sb        = ext2_get_sb, // указатель на функцию возвращающую суперблок
    .kill_sb    = kill_block_super,  // соответственно функция убивающая суперблок
    .fs_flags    = FS_REQUIRES_DEV,
};

static int __init init_ext2_fs(void)
{
    int err = init_ext2_xattr();  // инициализация дополнительных атрибутов... пока не интересно
    if (err)
        return err;
    err = init_inodecache();  // а вот тут начинаются проблемы... не понимаю, что за кеш, а самое главное как из этого кеша вытаскиваются иноды (см. дальше)
    if (err)
        goto out1;
        err = register_filesystem(&ext2_fs_type);  // регистрация файловой системы
    if (err)
        goto out;
    return 0;
// всякие откаты на случай ошибок
out:
    destroy_inodecache();
out1:
    exit_ext2_xattr();
    return err;
}

сначала посмотрим на ргистрацию ФC
fs/filesystem.c   register_filesystem(struct file_system_type * fs)

+ открыть спойлер
/**
 *    register_filesystem - register a new filesystem
 *    @fs: the file system structure
 *
 *    Adds the file system passed to the list of file systems the kernel
 *    is aware of for mount and other syscalls. Returns 0 on success,
 *    or a negative errno code on an error.
 *
 *    The &struct file_system_type that is passed is linked into the kernel 
 *    structures and must not be freed until the file system has been
 *    unregistered.
 */
 
int register_filesystem(struct file_system_type * fs)
{
    int res = 0;
    struct file_system_type ** p;

    BUG_ON(strchr(fs->name, '.'));
    if (fs->next)
        return -EBUSY;
    INIT_LIST_HEAD(&fs->fs_supers); //обнуление списка суперблоков
    write_lock(&file_systems_lock);
    p = find_filesystem(fs->name, strlen(fs->name));  // ещет по имени, не добавлена ли уже такая fs

    if (*p)
        res = -EBUSY;
    else
        *p = fs; // добавление ФС в хвост списка (хитрый финт см. функцию  find_filesystem)
    write_unlock(&file_systems_lock);
    return res;
}

! указатель на начало списка ФС хранится в глобальной переменно *file_systems

include/linux/fs.h struct file_system_type

+ открыть спойлер
struct file_system_type {
    const char *name; //имя
    int fs_flags;
    int (*get_sb) (struct file_system_type *, int,
               const char *, void *, struct vfsmount *);
    void (*kill_sb) (struct super_block *); 
    struct module *owner; //модуль, владеющий ФС, видимо для дебага, или если модуль выгружают, чтобы ФС тоже автоматом выгружалась...
    struct file_system_type * next; // следующая ФС в списке
    struct list_head fs_supers; //заголовок списка суперблоков
//....
// тут ещё какие-то блокировки...
};

// to be continued...

95% процентов проблем находятся между клавиатурой и стулом.

10

а теперь функция, инициализирующая кеш инодов  oO
fs/filesystem.c   init_inodecache();  init_once(void *foo)

+ открыть спойлер
// вызывается калбеком откуда-то из кеша...
static void init_once(void *foo)
{
    struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
    // тип инода ext2 для представления в памяти
    rwlock_init(&ei->i_meta_lock);
#ifdef CONFIG_EXT2_FS_XATTR
    init_rwsem(&ei->xattr_sem);
#endif
    mutex_init(&ei->truncate_mutex);
    inode_init_once(&ei->vfs_inode); //забивает инод значениями по умолчанию
}

static int init_inodecache(void)
{
    // пока понятия не имею как работают кеши и с чем их едят... 
    // но тут он, очевидно, создаётся
    ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
                         sizeof(struct ext2_inode_info),
                         0, (SLAB_RECLAIM_ACCOUNT|
                        SLAB_MEM_SPREAD),
                         init_once);
    if (ext2_inode_cachep == NULL)
        return -ENOMEM;
    return 0;
}

описатель структуры:
fs/ext2/ext2.h   struct ext2_inode_info

+ открыть спойлер
/*
 * second extended file system inode data in memory
 */
// часть полей и коментариев пропущено
struct ext2_inode_info {
    __le32    i_data[15];
    __u32    i_flags;
    __u32    i_faddr;
    __u8    i_frag_no;
    __u8    i_frag_size;
    __u16    i_state;
    __u32    i_file_acl;
    __u32    i_dir_acl;
    __u32    i_dtime;
    __u32    i_block_group;
    struct ext2_block_alloc_info *i_block_alloc_info;

    __u32    i_dir_start_lookup;
    rwlock_t i_meta_lock;

    struct mutex truncate_mutex;
    struct inode    vfs_inode; // инод vfs
    struct list_head i_orphan;    /* unlinked but open inodes */
};

приведу описатель структуры что б было
include/linux/fs.h   struct inode

+ открыть спойлер
struct inode {
    struct hlist_node    i_hash;
    struct list_head    i_list;        /* backing dev IO list */
    struct list_head    i_sb_list;
    struct list_head    i_dentry;
    unsigned long    i_ino;
    atomic_t        i_count;
    unsigned int    i_nlink;
    uid_t        i_uid;
    gid_t        i_gid;
    dev_t        i_rdev;
    unsigned int    i_blkbits;
    u64        i_version;
    loff_t        i_size;
#ifdef __NEED_I_SIZE_ORDERED
    seqcount_t        i_size_seqcount;
#endif
    struct timespec    i_atime;
    struct timespec    i_mtime;
    struct timespec    i_ctime;
    blkcnt_t        i_blocks;
    unsigned short       i_bytes;
    umode_t        i_mode;
    spinlock_t    i_lock;    /* i_blocks, i_bytes, maybe i_size */
    struct mutex    i_mutex;
    struct rw_semaphore    i_alloc_sem;
    const struct inode_operations    *i_op;
    const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */
    struct super_block    *i_sb;
    struct file_lock    *i_flock;
    struct address_space    *i_mapping;
    struct address_space    i_data;
#ifdef CONFIG_QUOTA
    struct dquot        *i_dquot[MAXQUOTAS];
#endif
    struct list_head    i_devices;
    union {
        struct pipe_inode_info    *i_pipe;
        struct block_device    *i_bdev;
        struct cdev        *i_cdev;
    };

    __u32            i_generation;

#ifdef CONFIG_FSNOTIFY
    __u32            i_fsnotify_mask; /* all events this inode cares about */
    struct hlist_head    i_fsnotify_marks;
#endif

    unsigned long        i_state;
    unsigned long        dirtied_when;    /* jiffies of first dirtying */

    unsigned int        i_flags;

    atomic_t        i_writecount;
#ifdef CONFIG_SECURITY
    void            *i_security;
#endif
#ifdef CONFIG_FS_POSIX_ACL
    struct posix_acl    *i_acl;
    struct posix_acl    *i_default_acl;
#endif
    void            *i_private; /* fs or device private pointer */
};

kmem_cache_create полностью приводить не буду, напишу только, что он делает с возвращаемым значением:
mm/slab.c   struct kmem_cache *kmem_cache_create ()

+ открыть спойлер
struct kmem_cache *
kmem_cache_create (const char *name, size_t size, size_t align,
    unsigned long flags, void (*ctor)(void *))
{
    size_t left_over, slab_size, ralign;
    struct kmem_cache *cachep = NULL, *pc;
    gfp_t gfp;
//....

    cachep = kmem_cache_zalloc(&cache_cache, gfp);
    if (!cachep)
        goto oops;

//....

    /*
     * Determine if the slab management is 'on' or 'off' slab.
     * (bootstrapping cannot cope with offslab caches so don't do
     * it too early on. Always use on-slab management when
     * SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
     */
    if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
        !(flags & SLAB_NOLEAKTRACE))
        /*
         * Size is large, assume best to place the slab management obj
         * off-slab (should allow better packing of objs).
         */
        flags |= CFLGS_OFF_SLAB;

    size = ALIGN(size, align);

    left_over = calculate_slab_order(cachep, size, align, flags);

    if (!cachep->num) {
        printk(KERN_ERR
               "kmem_cache_create: couldn't create cache %s.\n", name);
        kmem_cache_free(&cache_cache, cachep);
        cachep = NULL;
        goto oops;
    }
    slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
              + sizeof(struct slab), align);

    /*
     * If the slab has been placed off-slab, and we have enough space then
     * move it on-slab. This is at the expense of any extra colouring.
     */
    if (flags & CFLGS_OFF_SLAB && left_over >= slab_size) {
        flags &= ~CFLGS_OFF_SLAB;
        left_over -= slab_size;
    }

    if (flags & CFLGS_OFF_SLAB) {
        /* really off slab. No need for manual alignment */
        slab_size =
            cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);

#ifdef CONFIG_PAGE_POISONING
        /* If we're going to use the generic kernel_map_pages()
         * poisoning, then it's going to smash the contents of
         * the redzone and userword anyhow, so switch them off.
         */
        if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
            flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
#endif
    }

    cachep->colour_off = cache_line_size();
    /* Offset must be a multiple of the alignment. */
    if (cachep->colour_off < align)
        cachep->colour_off = align;
    cachep->colour = left_over / cachep->colour_off;
    cachep->slab_size = slab_size;
    cachep->flags = flags;
    cachep->gfpflags = 0;
    if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
        cachep->gfpflags |= GFP_DMA;
    cachep->buffer_size = size;
    cachep->reciprocal_buffer_size = reciprocal_value(size);

    if (flags & CFLGS_OFF_SLAB) {
        cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
        /*
         * This is a possibility for one of the malloc_sizes caches.
         * But since we go off slab only for object size greater than
         * PAGE_SIZE/8, and malloc_sizes gets created in ascending order,
         * this should not happen at all.
         * But leave a BUG_ON for some lucky dude.
         */
        BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
    }
    cachep->ctor = ctor;
    cachep->name = name;

    if (setup_cpu_cache(cachep, gfp)) {
        __kmem_cache_destroy(cachep);
        cachep = NULL;
        goto oops;
    }

    /* cache setup completed, link it into the list */
    list_add(&cachep->next, &cache_chain);
oops:
    if (!cachep && (flags & SLAB_PANIC))
        panic("kmem_cache_create(): failed to create slab `%s'\n",
              name);
    if (slab_is_available()) {
        mutex_unlock(&cache_chain_mutex);
        put_online_cpus();
    }
    return cachep;
}

приведу kmem_cache
mm/slab.c   struct kmem_cache

+ открыть спойлер
struct kmem_cache {
    unsigned int size, align;
    unsigned long flags;
    const char *name;
    void (*ctor)(void *);
};

если кто знает, может разжевать что такое кеш и с чем его едят?

95% процентов проблем находятся между клавиатурой и стулом.

11

у кэша во все времена было два значения
а) наличность (наличные деньги)
б) некие промежуточные результаты или данные, которые требуются постоянно в процессе работы
читали это?
http://www.interface.ru/home.asp?artId=8660
вдруг поможет...

ПатреГ не любит Gnome...

12

ну не читать-же каждый раз иноды с диска? вот они и лежат в памяти - читаются ОДИН раз. причём сразу блоком, ЕМНИП в 4096байт (один инод сейчас в 256 байт). это и называется "кеширование".
кстати, иноды создаются 1 раз при форматировании, их очень много - сотни тысяч, и даже миллионы. Потому читать их ВСЕ невозможно. Приходится читать по мере запросов. В FAT'е читалась вся таблица. В NTFS похоже, но там обычно таблица инодов непрерывная (MFT), и лежит точно в центре диска. В EXT таблица разорвана на куски, и куски разбросаны по всей поверхности. Причём координаты таблиц инодов никогда не меняются, и записаны они в суперблоках (которые тоже равномерно разбросаны по всему разделу. но нужен только один, первый суперблок, остальные для резерва).

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

13

Fat-Zer пишет:

приведу описатель структуры что б было

что-то добавили, что-то убавили... это EXT4?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

14

спасибо... понял при чём здесь кеш, оказалось всё достаточно просто и логично... просто одна книжка ввела в заблуждение.

drBatty пишет:
Fat-Zer пишет:

приведу описатель структуры что б было

что-то добавили, что-то убавили... это EXT4?

это из include/linux/fs.h, т.е. одна структура для всех ФС... похоже для представления инода в памяти...

95% процентов проблем находятся между клавиатурой и стулом.

15

Fat-Zer пишет:

это из include/linux/fs.h, т.е. одна структура для всех ФС... похоже для представления инода в памяти...

а... а я смотрел на диске. логично, что в памяти лежат только живые файлы. потому там и нет времени удаления. на диске структура совершенно другая.

Как я понял, сейчас есть только EXT4, EXT2 и EXT3 получаются из четвёрки отключением некоторых фич.

Получается, что при чтении инода он теперь кардинально переделывается (ЕМНИП раньше он просто тупо читался, и структура была точно такой-же).

Я вот что подумал: дело в том, что у ядра имеется СВОЯ, личная память. Мало того, ВСЕ алгоритмы внутри ядра имеют гарантированное потребление памяти. К примеру, внутри ядра не применяется qsort(), причина проста - qsort() имеет худший случай - когда время исполнения и объём памяти равен N*N - если N равно например 1000000, то N*N = 10^12, что приведёт даже для 32х битных систем к потреблению как минимум 10^14 байт. (кстати в венде не так. потому она иногда виснет, а иногда просто падает. Редко, но бывает). Проблема в том, что инодов может потребоваться ОЧЕНЬ много, потому просто так этот кеш в ядро не запихаешь. Однако, несколько лет таки запихали. ИМХО как раз это и привело к трудноуловимому глюку. ИМХО этот "глюк" так и не исправили, просто число файлов увеличилось не так быстро, как память   :lol:

А линух как тормозил, так и сейчас тормозит при копировании файлов, если этих файлов много. ИЧСХ, область памяти ядра скрыта даже от рута, и невидима - получается так, что кажется, что памяти хватает, но на самом деле, её недостаточно. Как доказал Кнут ещё в середине прошлого века, любая система будет сильно тормозить при нехватке памяти. Вот мы и имеем - кажется (даже руту), что памяти достаточно, но её не хватает. Ядро судорожно гоняет данные с места на место, при этом загрузка памяти 70%, загрузка CPU 0%, но всё тупит и тормозит. Это принципиально не лечится. Ядро венды ввести в такой режим ещё проще, просто мало кому это нужно. А вот в линуксе мы имеем отличную EXT, которая поддерживает огромное количество файлов сразу, чем усиленно пользуются кодеры...

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

что это было?
это тоже необходимо знать?  :o  :o  :o

//

17

сантехник пишет:

что это было?
это тоже необходимо знать?

если вы собираетесь разрабатывать ФС - да.  smile

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

в линуксе этих фс.. черт ногу сломает.
зачем усложнять себе жись?

//

19

drBatty пишет:

Как я понял, сейчас есть только EXT4, EXT2 и EXT3 получаются из четвёрки отключением некоторых фич.

почему? в дереве сырцов отдельно лежат fs/ext2/, fs/ext3/, fs/ext4/ и содержимое в них достаточно сильно(если не полностью) различается.

drBatty пишет:

Получается, что при чтении инода он теперь кардинально переделывается (ЕМНИП раньше он просто тупо читался, и структура была точно такой-же).

это тоже достаточно логично... всё таки поддерживаем не одну ФС...

drBatty пишет:

К примеру, внутри ядра не применяется qsort(), причина проста - qsort() имеет худший случай - когда время исполнения и объём памяти равен N*N - если N равно например 1000000, то N*N = 10^12, что приведёт даже для 32х битных систем к потреблению как минимум 10^14 байт.

это по времени худший случай О(n^2), а памяти он используется не более O(n). да и улучшить можно: если глубина рекурсии достигает опасного n, то вызываем какой-нить пузырёк для подмассивов.

drBatty пишет:

ИМХО как раз это и привело к трудноуловимому глюку.

можно поподробней, а то я этого не застал smile

drBatty пишет:

ИЧСХ, область памяти ядра скрыта даже от рута, и невидима - получается так, что кажется, что памяти хватает, но на самом деле, её недостаточно.

о_О вот эту строчку не переварил... не представляю, как такое может быть(то что скрыта от рута, да и как вообще неучтённая память может быть...)  oO

сантехник пишет:

в линуксе этих фс.. черт ногу сломает.
зачем усложнять себе жись?

ни кто за вами бегать с палкой и заставлять использовать что-то конкретное не будет. а зачем - как минимум самообразование.

95% процентов проблем находятся между клавиатурой и стулом.

20

Fat-Zer пишет:

почему? в дереве сырцов отдельно лежат fs/ext2/, fs/ext3/, fs/ext4/ и содержимое в них достаточно сильно(если не полностью) различается.

как я понял, в ядро вкомпилливается только EXT4. но можно засунуть и лишь EXT2, например для встроенных систем без HDD.

Fat-Zer пишет:

это тоже достаточно логично... всё таки поддерживаем не одну ФС...

логично. я не спорю. просто раньше похоже было по другому. конечно в итоге всё и так приводилось к общему знаменателю, но уже дальше по коду.

Fat-Zer пишет:

это по времени худший случай О(n^2), а памяти он используется не более O(n). да и улучшить можно: если глубина рекурсии достигает опасного n, то вызываем какой-нить пузырёк для подмассивов.

ну O(N) это обычно тоже ОЧЕНЬ много. Учитывая, что рассчитывают таки на log2(N).

Fat-Zer пишет:

да и улучшить можно: если глубина рекурсии достигает опасного n, то вызываем какой-нить пузырёк для подмассивов.

проще не парится, а взять другую сортировку, ЕМНИП так и было сделано. (используется метод Шелла).

Fat-Zer пишет:

можно поподробней, а то я этого не застал

недавно было. совпало по времени со сменой hda на sda (у меня во всяком случае). Там при операциях с файлами всё жутко тупило, мышкой по кнопке нельзя было кликнуть. А загрузка около 0.
многие не застали - этот глюк проявлялся как-то рандомно - типа на дистре XYZ и мамке ABC есть, а на другой мамке/дистре - нету.

Fat-Zer пишет:

вот эту строчку не переварил... не представляю, как такое может быть(то что скрыта от рута, да и как вообще неучтённая память может быть...)

да говорю-же: глюк. Рут спрашивает ядро: "сколько памяти?", ядро отвечает 100. И нагло врёт. ac

сантехник пишет:

в линуксе этих фс.. черт ногу сломает.
зачем усложнять себе жись?

для более эффективного использования инструмента надо знать его свойства. Что-бы было ясно, когда применить шило, когда отвёртку, а когда - лом.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

21

drBatty пишет:

как я понял, в ядро вкомпилливается только EXT4. но можно засунуть и лишь EXT2, например для встроенных систем без HDD.

не верю я чего-то... при сборке ядра всё же собирается отдельно. Есть пруфлинк или идеи, как это проверить?

95% процентов проблем находятся между клавиатурой и стулом.

22 (17.02.2011 00:21:09 отредактировано Fat-Zer)

ещё вопрос... как иноды адресуют информацию на диске? и есть ли различия в структуре инодов для каталогов/устройств/труб итп?
а теперь.... следующий кусок кода на разбор...

fs/ext2/super.c static int ext2_get_sb()

+ открыть спойлер
static int ext2_get_sb(struct file_system_type *fs_type,
    int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
    return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);
}

ничего примечательного... важно что передаём указатель на функцию ext2_fill_super().

похоже оно занимается чтением суперблока с блочного устройства... хотя собственно чтения я тут не заметил:
fs/super.c static int get_sb_bdev()

+ открыть спойлер
int get_sb_bdev(struct file_system_type *fs_type,
    int flags, const char *dev_name, void *data,
    int (*fill_super)(struct super_block *, void *, int),
    struct vfsmount *mnt)
{
    struct block_device *bdev;
    struct super_block *s;
    fmode_t mode = FMODE_READ;
    int error = 0;

    if (!(flags & MS_RDONLY)) //если не ридонли, то разрешаем запись
        mode |= FMODE_WRITE;

    bdev = open_bdev_exclusive(dev_name, mode, fs_type);  //открываем блочное устройство
    if (IS_ERR(bdev))  // ошибка при ахтунге
        return PTR_ERR(bdev); 

    /*
     * once the super is inserted into the list by sget, s_umount
     * will protect the lockfs code from trying to start a snapshot
     * while we are mounting
     */
    mutex_lock(&bdev->bd_fsfreeze_mutex);
    if (bdev->bd_fsfreeze_count > 0) {  // не очень понятно, что мы тут проверяем.. что за замороженные процессы...
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        error = -EBUSY;
        goto error_bdev;
    }
    s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);  // собственно ищет и создаёт суперблок
    mutex_unlock(&bdev->bd_fsfreeze_mutex);
    if (IS_ERR(s))
        goto error_s;
    // не понятно, кто бы мог это установить... похоже где-то в тёмной части c test в sget
    if (s->s_root) {
        if ((flags ^ s->s_flags) & MS_RDONLY) {
            deactivate_locked_super(s);
            error = -EBUSY;
            goto error_bdev;
        }

        /*
         * s_umount nests inside bd_mutex during
         * __invalidate_device().  close_bdev_exclusive()
         * acquires bd_mutex and can't be called under
         * s_umount.  Drop s_umount temporarily.  This is safe
         * as we're holding an active reference.
         */
        up_write(&s->s_umount);
        close_bdev_exclusive(bdev, mode);
        down_write(&s->s_umount);
    } else {
        char b[BDEVNAME_SIZE];

        s->s_flags = flags; // устанавливаем флаги
        s->s_mode = mode; // режим
        strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));  // заменяем имя
        sb_set_blocksize(s, block_size(bdev));  // устанавливаем размер блока
        error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);  //!!!калл-бек в модуль ФС
        if (error) {
            deactivate_locked_super(s);
            goto error;
        }

        s->s_flags |= MS_ACTIVE;
        bdev->bd_super = s;
    }

    simple_set_mnt(mnt, s);
    return 0;

error_s:
    error = PTR_ERR(s);
error_bdev:
    close_bdev_exclusive(bdev, mode);
error:
    return error;
}

fs/super.c struct super_block *sget()

+ открыть спойлер
/**
 *    sget    -    find or create a superblock
 *    @type:    filesystem type superblock should belong to
 *    @test:    comparison callback
 *    @set:    setup callback
 *    @data:    argument to each of them
 */
struct super_block *sget(struct file_system_type *type,
            int (*test)(struct super_block *,void *),
            int (*set)(struct super_block *,void *),
            void *data)
{
    struct super_block *s = NULL;
    struct super_block *old;
    int err;

retry:
    spin_lock(&sb_lock);
    if (test) {// если нам передали указатель на функцию тестирования суперблока, то проходим по всем спискам суперблоков для ФС и перепроверяем их(если не ошибыюсь)
        list_for_each_entry(old, &type->fs_supers, s_instances) {
            if (!test(old, data))
                continue;
            if (!grab_super(old))
                goto retry;
            if (s) {
                up_write(&s->s_umount);
                destroy_super(s);
                s = NULL;
            }
            down_write(&old->s_umount);
            if (unlikely(!(old->s_flags & MS_BORN))) {
                deactivate_locked_super(old);
                goto retry;
            }
            return old; 
        }
    }
    if (!s) { // если указатель на суперблок ==нулю(а это скорей всего так), то пытаемся его создать
        spin_unlock(&sb_lock);
        s = alloc_super(type);
        if (!s)
            return ERR_PTR(-ENOMEM);
        goto retry;
    }
        
    err = set(s, data); // калл-бек
    if (err) { 
        spin_unlock(&sb_lock);
        up_write(&s->s_umount);
        destroy_super(s);
        return ERR_PTR(err);
    }
    s->s_type = type;  // начинаем заполнение структуры... устанавливаем тип ФС
    strlcpy(s->s_id, type->name, sizeof(s->s_id));  //устанавливаем ID ФС суперблока
    list_add_tail(&s->s_list, &super_blocks);  //добавляет новый суперблок в конец списка СБ
    list_add(&s->s_instances, &type->fs_supers);  // добавляет суперблок в список суперблоков ФС
    spin_unlock(&sb_lock);  
    get_filesystem(type);  //!!! похоже подгружает модуль для ФС (поправте меня)!!!
    return s;
}

в общем не понятно , что за тёмное дело с test делается... 
и вроде там может возникнуть ситуация, когда спинблокировку второй раз пытаемя захватить...  oO
и ещё get_filesystem не совсем уверен, что делает

в следуещем посте рассмотрю ext2_fill_super()

95% процентов проблем находятся между клавиатурой и стулом.

23

Fat-Zer пишет:

не верю я чего-то... при сборке ядра всё же собирается отдельно. Есть пруфлинк или идеи, как это проверить?

ИМХО проще всего попробовать собрать ядро без 2 и 3, и потом mkfs.ext2.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

24 (17.02.2011 15:33:04 отредактировано Fat-Zer)

drBatty пишет:

ИМХО проще всего попробовать собрать ядро без 2 и 3, и потом mkfs.ext2.

А разве mkfs не полностью в юзерспейсе работает и от модулей ФС ядра вообще не зависит? А вот монтировать он точно отказывается (помню в первый раз, когда собирал, отключил ext2 и /boot не монтировался...) конечно можно смонтировать 2 как 3(или 4)... но это уже история обратной совместимости.

[added] Только что попробовал создать рейзер4, хотя в ядре им и не пахнет...  получилось, смонтировать само собой - фейл... Итого: создание ФС не зависит от ядра ни как

95% процентов проблем находятся между клавиатурой и стулом.

25 (19.02.2011 19:04:50 отредактировано Fat-Zer)

код ext2_fill_super() расписывать нет больше ни желание, ни необходимости, ибо эта зараза занимает без малого четыре сотни строк. Так что опишу просто основные действия/данные, на что ИМХО стоит обратить внимание:

fs/ext2/super.c static int ext2_fill_super()

+ открыть спойлер
static int ext2_fill_super(struct super_block *sb, void *data, int silent)
// sb - структура суперблока, которую заполняем
// data - данные, которые передали транзитом (А кстати откуда эти данные пришли и что это такое?) 
//     судя по всему это опции монтирования в виде простой текстовой строки...
{
    struct buffer_head * bh;    // заголовок буфера чтения
    struct ext2_sb_info * sbi;    // указатель на эти данные, специфические для ФС будет хранится в суперблоке
    struct ext2_super_block * es;    // структура суперблока, так, как она хранится на диске

// ...

    if (blocksize != BLOCK_SIZE) { // перещёт смешения, если суперблок находится не на границе блока устройства
        logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
        offset = (sb_block*BLOCK_SIZE) % blocksize;
    } else {
        logic_sb_block = sb_block; 
    }
    if (!(bh = sb_bread(sb, logic_sb_block))) { // собственно создание и чтение в буффер суперблока
        ext2_msg(sb, KERN_ERR, "error: unable to read superblock");
        goto failed_sbi;
    }
// ...
// потом уставливаем дефолтные значения
// правим их в зависимости от опций монтирования
// проверка, не попытались ли мы использовать какие-то неподдерживаемые опции
// копирование разнообразных параметров в sbi
// ...
// что-то про группы, фрагменты итп... в общем в этом разбираться бесполезно, 
// пока более-менее не освоюсь в структуре ФС
// ...
// !а вот это очень важно!
    sb->s_op = &ext2_sops; // установка структуры-списка операций над ФС
    sb->s_export_op = &ext2_export_ops;  // не столь важные операции
    sb->s_xattr = ext2_xattr_handlers;  // операции над доп. атрибутами
// ...
    root = ext2_iget(sb, EXT2_ROOT_INO);  // чтение инода корня ФС
// ...
    sb->s_root = d_alloc_root(root);
// ...
    ext2_write_super(sb);  // не совсем понял, зачем нам записывать суперблок после того, как мы его загрузили
    return 0;
// ... обработка ошибок
}

fs/ext2/super.c static const struct super_operations ext2_sops

+ открыть спойлер
static const struct super_operations ext2_sops = {
    .alloc_inode     = ext2_alloc_inode,  // выделяем инод в кеше
    .destroy_inode   = ext2_destroy_inode,  // соответственно уничтожаем инод
    .write_inode     = ext2_write_inode,  // сохранение инода на диск
    .evict_inode     = ext2_evict_inode,  // пока не понял (???) может удаление
    .put_super       = ext2_put_super,    // освобождение суперблока
    .write_super     = ext2_write_super, // запись суперблока на диск
    .sync_fs         = ext2_sync_fs,   // записывает грязный суперблок надиск (вычитал в книжке, сильно в этом сомневаюсь)
    .statfs          = ext2_statfs,   // получение статистики ФС
    .remount_fs      = ext2_remount,  // перемонтирование ФС
    .show_options    = ext2_show_options,  // тоже пока загадка
#ifdef CONFIG_QUOTA
    .quota_read      = ext2_quota_read,
    .quota_write     = ext2_quota_write,
#endif
};

заметил, что переопределяются не все операции(например нет read_inode). Некоторые из них доступны по-умолчанию? где это можно увидеть?

Ещё: как рейзер упаковывает хвосты и мелкие файлы?

ЗЫ: наткнулся на статью о ext2(pdf), вроде это как раз то что нужно было.
ЗЗЫ: ещё хотелось бы что-нить почитать о структуре самой ФС ext2

95% процентов проблем находятся между клавиатурой и стулом.

26

Fat-Zer пишет:

Только что попробовал создать рейзер4, хотя в ядре им и не пахнет...  получилось, смонтировать само собой - фейл... Итого: создание ФС не зависит от ядра ни как

зависит. вопрос в том, модулем оно, или в самом ядре. mkfs естественно умеет и так и так.

Fat-Zer пишет:

А вот монтировать он точно отказывается (помню в первый раз, когда собирал, отключил ext2 и /boot не монтировался...)

ну ещё-бы! именно для того и делают /boot в EXT2, что-бы их поняли старинные загрузчики. т.е. прежде всего загрузчик должен прочитать ядро, потом ядро монтирует корневой раздел, потом оттуда грузятся модули.

Сейчас это всё не играет никакой роли, ибо и загрузчики, и ядра поддерживают EXT4.

Вы можете проверить, настоящая-ли у вас EXT2 - достаточно посмотреть, затирает-ли она нулями координаты блоков данных. EXT2 не затирает, а EXT3 без журнала - не затирает. Разница существенная, ибо на EXT3 без журнала не работает undelete.

создание ФС конечно от ядра и не должно зависить, но вот сможете-ли вы смонтировать вашу EXT2, или нет... И является-ли эта EXT2 действительно 2?...

Fat-Zer пишет:

data - данные, которые передали транзитом (А кстати откуда эти данные пришли и что это такое?)

это как раз самое интересное. Вот эти данные:
# tune2fs -l /dev/sda3

+ открыть спойлер

tune2fs 1.41.11 (14-Mar-2010)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          4a9c664f-c241-4dd5-be99-399d1ae205ca
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:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              449680
Block count:              1795255
Reserved block count:     89762
Free blocks:              404665
Free inodes:              163994
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      438
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8176
Inode blocks per group:   511
Flex block group size:    16
Filesystem created:       Wed Feb 16 19:52:45 2011
Last mount time:          Sat Feb 19 21:30:27 2011
Last write time:          Wed Feb 16 20:41:50 2011
Mount count:              5
Maximum mount count:      36
Last checked:             Wed Feb 16 19:52:45 2011
Check interval:           15552000 (6 months)
Next check after:         Mon Aug 15 20:52:45 2011
Lifetime writes:          6439 MB
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:       144828
Default directory hash:   half_md4
Directory Hash Seed:      753c461d-c8a4-4ca4-a77a-4ba9ff788bfc
Journal backup:           inode blocks

Fat-Zer пишет:

.sync_fs = ext2_sync_fs, // записывает грязный суперблок надиск (вычитал в книжке, сильно в этом сомневаюсь)

"грязный" в том смысле, что например произошло создание файла, и соответственно число свободных инодов уменьшилось. дело в том, что суперблок обычно расположен далеко от данных, и что-бы лишний раз не дёргать головками, запись в суперблок откладывается до выполнения этой функции. Она выполняется либо ядром, когда нечего делать, либо во время размонтирования носителя.

Fat-Zer пишет:

.show_options = ext2_show_options, // тоже пока загадка

в зависимости от версии ФС не все фичи могут быть доступны, например ACL, которая по умолчанию выключена. Но её можно и включить. Естественно необходим механизм для проверки этого.

Fat-Zer пишет:

ещё хотелось бы что-нить почитать о структуре самой ФС ext2

где-то у меня валялось годное описание, поищу...

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

27

drBatty пишет:

зависит. вопрос в том, модулем оно, или в самом ядре. mkfs естественно умеет и так и так.

в том то и идея... оно вообще выпилено из ядра (и модуль не собран, само собой).

drBatty пишет:

Вы можете проверить, настоящая-ли у вас EXT2 - достаточно посмотреть, затирает-ли она нулями координаты блоков данных. EXT2 не затирает, а EXT3 без журнала - не затирает. Разница существенная, ибо на EXT3 без журнала не работает undelete.

не совсем согласен: затирание - дело драйвера. Если драйвер ext2 не знает о том, что нужно затирать нулями, то за него магическая сила это делать не будет...

drBatty пишет:

создание ФС конечно от ядра и не должно зависить, но вот сможете-ли вы смонтировать вашу EXT2, или нет... И является-ли эта EXT2 действительно 2?...

вопрос не совсем понятен у extX в том и прелесть, что они обладают совместимостью во всех направлениях(и обратной и прямой). А то что (у меня) 2 - это действительно 2 я уверен(как минимум работает человеческий undelete)

drBatty пишет:

"грязный" в том смысле, что например произошло создание файла, и соответственно число свободных инодов уменьшилось. дело в том, что суперблок обычно расположен далеко от данных, и что-бы лишний раз не дёргать головками, запись в суперблок откладывается до выполнения этой функции. Она выполняется либо ядром, когда нечего делать, либо во время размонтирования носителя.

это понятно... просто ёкнуло, что должны сбрасываться ещё и буферы данных... сейчас вспомнил, что буферизация данных находится на уровне устройств.

drBatty пишет:

это как раз самое интересное. Вот эти данные:
# tune2fs -l /dev/sda3

интересно, но не то... это текстовая строка, в которой, как минимум, может находится "sb=N" (N - смещение с которого читаем суперблок). Вопрос был откуда она по коду приходит (есть предположение, что она идёт из mount). Это было в той части, которую я опустил.

    unsigned long sb_block = get_sb_block(&data);

fs/ext2/super.c static unsigned long get_sb_block()

+ открыть спойлер
static unsigned long get_sb_block(void **data)
{
    unsigned long     sb_block;
    char         *options = (char *) *data;

    if (!options || strncmp(options, "sb=", 3) != 0)
        return 1;    /* Default location */
    options += 3;
    sb_block = simple_strtoul(options, &options, 0);
    if (*options && *options != ',') {
        printk("EXT2-fs: Invalid sb specification: %s\n",
               (char *) *data);
        return 1;
    }
    if (*options == ',')
        options++;
    *data = (void *) options;
    return sb_block;
}

а то что вы назвали должно содержаться в es или sbi(если смотреть по коду)

drBatty пишет:

в зависимости от версии ФС не все фичи могут быть доступны, например ACL, которая по умолчанию выключена. Но её можно и включить. Естественно необходим механизм для проверки этого.

понял, правда тут, наверное в зависимости от того как модуль собран зависит...

drBatty пишет:

где-то у меня валялось годное описание, поищу...

заранее спасибо.

95% процентов проблем находятся между клавиатурой и стулом.

28

для полноты картины не хватало:
include/linux/fs.h struct super_block

+ открыть спойлер
struct super_block {
    struct list_head    s_list;        /* Keep this first */  // заголовок списка суперблоков
    dev_t            s_dev;        /* search index; _not_ kdev_t */ // пока не ясно что это
    unsigned char        s_dirt;  // флаг грязности инода
    unsigned char        s_blocksize_bits; // ???
    unsigned long        s_blocksize; // размер блока данных
    loff_t            s_maxbytes;    /* Max file size */
    struct file_system_type    *s_type;  // указатель на тип ФС ()
    const struct super_operations    *s_op;  // список доступных операций
    const struct dquot_operations    *dq_op;  // операции связанные с квотами
    const struct quotactl_ops    *s_qcop;  // в ту же степь
    const struct export_operations *s_export_op;  //ещё какие-то операции
    unsigned long        s_flags;  // флаги какие-то
    unsigned long        s_magic; // что за магическое число до сих пор не понимаю... (похоже или UUID, или уникальный для каждого типа ФС)
    struct dentry        *s_root;  // указатель на структуру связанную с корнем
    struct rw_semaphore    s_umount; // видимо блокировка отмонтирования при работе с ФС
    struct mutex        s_lock; // а это бокировка на монопольный доступ к ФС
    int            s_count; // ???
    atomic_t        s_active; // ???
#ifdef CONFIG_SECURITY
    void                    *s_security;
#endif
    const struct xattr_handler **s_xattr;  // тоже операции/обработчики чего-то связанного с xattr'ами 

    struct list_head    s_inodes;    /* all inodes */
    struct hlist_head    s_anon;        /* anonymous dentries for (nfs) exporting */
#ifdef CONFIG_SMP
    struct list_head __percpu *s_files;
#else
    struct list_head    s_files;  // список открытых файлов 
#endif
    /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
    struct list_head    s_dentry_lru;    /* unused dentry lru */
    int            s_nr_dentry_unused;    /* # of dentry on lru */

    struct block_device    *s_bdev;  // блочное устройство, ассоциированное с ФС
    struct backing_dev_info *s_bdi;  // ???
    struct mtd_info        *s_mtd; // ???
    struct list_head    s_instances; // ???
    struct quota_info    s_dquot;    /* Diskquota specific options */

    int            s_frozen; // ???
    wait_queue_head_t    s_wait_unfrozen; // ???

    char s_id[32];                /* Informational name */

    void             *s_fs_info;    /* Filesystem private info */
    fmode_t            s_mode; // ???

    /* Granularity of c/m/atime in ns.
       Cannot be worse than a second */
    u32           s_time_gran; // надо понять, что такое грунул[ярность/ирование]

    /*
     * The next field is for VFS *only*. No filesystems have any business
     * even looking at it. You had been warned.
     */
    struct mutex s_vfs_rename_mutex;    /* Kludge */ 

    /*
     * Filesystem subtype.  If non-empty the filesystem type field
     * in /proc/mounts will be "type.subtype"
     */
    char *s_subtype;

    /*
     * Saved mount options for lazy filesystems using
     * generic_show_options()
     */
    char *s_options;  // опа на...
};
drBatty пишет:
Fat-Zer пишет:


.show_options = ext2_show_options, // тоже пока загадка

в зависимости от версии ФС не все фичи могут быть доступны, например ACL, которая по умолчанию выключена. Но её можно и включить. Естественно необходим механизм для проверки этого.

и всё таки оно показывает только опции монтирования... в текстовом виде(см. последний член структуры)

95% процентов проблем находятся между клавиатурой и стулом.

29

Fat-Zer пишет:

вопрос не совсем понятен у extX в том и прелесть, что они обладают совместимостью во всех направлениях(и обратной и прямой). А то что (у меня) 2 - это действительно 2 я уверен(как минимум работает человеческий undelete)

а у меня не работает...

Fat-Zer пишет:

unsigned char s_blocksize_bits; // ???

ЕМНИП это тоже что и размер блока, только для скорости оно как-то по другому записано. вроде-бы там логарифм от 2, для того-что-бы скажем сдвинуть число влево на 12, и получить из числа блоков байты. (12 == log2(4096))

Fat-Zer пишет:

// что за магическое число до сих пор не понимаю... (похоже или UUID, или уникальный для каждого типа ФС)

это тип FS. если команде mount не указать ФС (auto), то она читает суперблок, и если в нужном месте число 0xEF53, она предполагает, что это какая-то EXT. Это не очень надёжно конечно, с вероятностью 1/65536 она может принять данные скажем из NTFS как EXT, и соответственно напишет "инвалидный суперблок".

Fat-Zer пишет:

int s_count; // ???

скорее всего это счётчик свободных блоков. надо дальше по коду смотреть...

Fat-Zer пишет:

struct mtd_info *s_mtd; // ???

ЕМНИП когда и как монтировалась ФС в посл. раз.

Fat-Zer пишет:

и всё таки оно показывает только опции монтирования... в текстовом виде(см. последний член структуры)

ну значит так...

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

30

drBatty пишет:
Fat-Zer пишет:

вопрос не совсем понятен у extX в том и прелесть, что они обладают совместимостью во всех направлениях(и обратной и прямой). А то что (у меня) 2 - это действительно 2 я уверен(как минимум работает человеческий undelete)

а у меня не работает...

был не прав:
ext2 монтируется как ext[2,4]
ext3 монтируется как ext[2,3,4]
ext4 монтируется как ext4 только

эксперементы:

+ открыть спойлер

 Консоль:

tmp # dd if=/dev/zero of=file
^C293108+0 записей считано
293107+0 записей написано
скопировано 150070784 байта (150 MB), 1,53825 c, 97,6 MB/c

tmp # mkfs.ext2 file
mke2fs 1.41.12 (17-May-2010)
file is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
36720 inodes, 146552 blocks
7327 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
18 block groups
8192 blocks per group, 8192 fragments per group
2040 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 24 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
tmp # mkdir mountdir
tmp # mount -o loop file mountdir/
tmp # cp /usr/portage/a* mountdir/ -R
tmp # umount mountdir/
tmp # sudo mount -t ext3 -o loop file mountdir/
mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error
       В некоторых случаях полезная информация может быть
       найдена в syslog - попробуйте dmesg | tail или что-то
       в этом роде

tmp # ls mountdir/
tmp # sudo mount -t ext4 -o loop file mountdir/
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  app-xemacs
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim   lost+found
tmp # rm -r mountdir/app-xemacs/
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  lost+found
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim
tmp # umount mountdir/
tmp # sudo mkfs.ext3 file
mke2fs 1.41.12 (17-May-2010)
file is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
36720 inodes, 146552 blocks
7327 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
18 block groups
8192 blocks per group, 8192 fragments per group
2040 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 26 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
tmp # sudo mount -t ext2 -o loop file mountdir/
tmp # cp /usr/portage/a* mountdir/ -R
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  app-xemacs
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim   lost+found
tmp # umount mountdir/
tmp # sudo mount -t ext3 -o loop file mountdir/
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  app-xemacs
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim   lost+found
tmp # umount mountdir/
tmp # sudo mount -t ext4 -o loop file mountdir/
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  app-xemacs
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim   lost+found
tmp # rm -r mountdir/app-xemacs/
tmp # ls mountdir/
app-accessibility  app-antivirus  app-backup      app-cdr    app-dicts  app-editors  app-emulation  app-i18n    app-misc         app-office  app-portage  app-text  lost+found
app-admin          app-arch       app-benchmarks  app-crypt  app-doc    app-emacs    app-forensics  app-laptop  app-mobilephone  app-pda     app-shells   app-vim
tmp # umount mountdir/
tmp # mkfs.ext4 file
mke2fs 1.41.12 (17-May-2010)
file is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
36720 inodes, 146552 blocks
7327 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
18 block groups
8192 blocks per group, 8192 fragments per group
2040 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 27 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
goblin tmp # mount -t ext2 -o loop file mountdir/
mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error
       В некоторых случаях полезная информация может быть
       найдена в syslog - попробуйте dmesg | tail или что-то
       в этом роде

tmp # mount -t ext3 -o loop file mountdir/
mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error
       В некоторых случаях полезная информация может быть
       найдена в syslog - попробуйте dmesg | tail или что-то
       в этом роде


ругань из dmesg:

[63516.350370] EXT3-fs (loop0): error: no journal found. mounting ext3 over ext2?
[63531.752337] EXT4-fs (loop0): mounted filesystem without journal. Opts: (null)
[64834.130508] EXT2-fs (loop0): warning: mounting ext3 filesystem as ext2
[64986.218178] EXT3-fs: barriers not enabled
[64986.218209] kjournald starting.  Commit interval 5 seconds
[64986.218242] EXT3-fs (loop0): using internal journal
[64986.218246] EXT3-fs (loop0): mounted filesystem with writeback data mode
[65001.334499] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null)
[65775.969452] EXT2-fs (loop0): error: couldn't mount because of unsupported optional features (240)
[65782.602635] EXT3-fs (loop0): error: couldn't mount because of unsupported optional features (240)
95% процентов проблем находятся между клавиатурой и стулом.