Почему с ENOENT происходит сбой при монтировании файла после отмены связи?

Попробуйте это:

cut -c 34- | cut -d '"' -f1

Первый cutудаляет первые 33 символа; второй cutсохраняет только часть перед первым ".

4
24.08.2019, 11:32
2 ответа

Просматривая исходный код, я нашел только один ENOENT, который был релевантным, то есть для несвязанной записи каталога:

static int attach_recursive_mnt(struct mount *source_mnt,
            struct mount *dest_mnt,
            struct mountpoint *dest_mp,
            struct path *parent_path)
{
    [...]

    /* Preallocate a mountpoint in case the new mounts need
     * to be tucked under other mounts.
     */
    smp = get_mountpoint(source_mnt->mnt.mnt_root);
static struct mountpoint *get_mountpoint(struct dentry *dentry)
{
    struct mountpoint *mp, *new = NULL;
    int ret;

    if (d_mountpoint(dentry)) {
        /* might be worth a WARN_ON() */
        if (d_unlinked(dentry))
            return ERR_PTR(-ENOENT);

https://elixir.bootlin.com/linux/v5.2/source/fs/namespace.c#L3100

get_mountpoint()обычно применяется к цели, а не к источнику. В этой функции она вызывается из-за распространения монтирования. Необходимо обеспечить соблюдение правила, запрещающего добавлять монтирования поверх удаленного файла во время распространения монтирования. Но принудительное выполнение происходит с готовностью, даже если не происходит распространения монтирования, которое потребовало бы этого. Я думаю, это хорошо, что проверка такая постоянная, просто она закодирована немного более неясно, чем я бы предпочел в идеале.

Как бы я ни смотрел на это, я думаю, что разумно применить это. До тех пор, пока это помогает сократить количество странных случаев для анализа, и ни у одного -нет особенно убедительного контраргумента -.

2
27.01.2020, 20:50

Полный ответ: :есть три вещи, которые нужно понять, и тогда все это имеет смысл.

Во-первых, источником связанного -монтирования является dentry , а не инод. То есть вы не привязываете -монтирование индексного дескриптора к имени; вы привязываете -монтируете один дентри к другому дентри. Чтобы увидеть разницу, посмотрите, что произойдет, если вы смонтируете разные ссылки на один и тот же индекс; крепления разные , потому что исходные дентри разные, даже если иноды одинаковые:

root@penguin:/tmp# echo hello > a1
root@penguin:/tmp# ln a1 a2
root@penguin:/tmp# touch b1 b2
root@penguin:/tmp# mount -B a1 b1
root@penguin:/tmp# mount -B a2 b2
root@penguin:/tmp# ls -li a1 a2 b1 b2
9552271 -rw-r--r-- 2 root root 6 Aug 25 05:16 a1
9552271 -rw-r--r-- 2 root root 6 Aug 25 05:16 a2
9552271 -rw-r--r-- 2 root root 6 Aug 25 05:16 b1
9552271 -rw-r--r-- 2 root root 6 Aug 25 05:16 b2
root@penguin:/tmp# grep /tmp/ /proc/self/mountinfo
421 364 0:38 /lxd/.../rootfs/tmp/a1 /tmp/b1 rw,...
422 364 0:38 /lxd/.../rootfs/tmp/a2 /tmp/b2 rw,...

Второе, что нужно понять, это то, что когда вы монтируете что-то, что само по себе является целью более раннего монтирования bind -, это тот же объект dentry, что и источник связывания -монтирования (, вот что связывает -монтаж есть; один дентри над другим. )Таким образом, если a1установлен на b1, то установка b1на c1точно такая же, как установка a1на c1, поскольку названия a1и b1относятся к к той же дентри.

Третье, что нужно понять, это то, что ядро ​​запрещает bind -монтировать удаленный dentry, потому что... я не вижу веских причин. Похоже, что применяется проверка ошибок, предназначенная для цели крепления (, предотвращающая установку поверх удаленного dentry, что не имеет смысла, поскольку вы никогда не сможете сослаться на новое крепление ). без уважительной причины к источнику монтировки.Вот этот код здесь:

static struct mountpoint *get_mountpoint(struct dentry *dentry)
{
    struct mountpoint *mp, *new = NULL;
    int ret;

    if (d_mountpoint(dentry)) {
        /* might be worth a WARN_ON() */
        if (d_unlinked(dentry))
            return ERR_PTR(-ENOENT);

Следствием этих трех фактов является (продолжение сеанса оболочки выше )ENOENTмонтирование b2на c2, если a2удалено:

root@penguin:/tmp# touch c1 c2
root@penguin:/tmp# rm a2
root@penguin:/tmp# mount -B b1 c1
root@penguin:/tmp# mount -B b2 c2
mount: mount(2) failed: /tmp/c2: No such file or directory
root@penguin:/tmp# 

Это кажется мне ошибкой, потому что ваш b2 -на -c2 действителен, если вы удалите a2 после ездового животного, и порядок не должен иметь значения :либо установка удаленного dentry на что-либо является законным или нет, не имеет значения, когда он был удален. Однако разумные люди с этим не согласны.

Всем спасибо.

0
27.01.2020, 20:50

Теги

Похожие вопросы