Por que a montagem acontece em um diretório existente?

49

Um diretório existente é necessário como um ponto de montagem .

$ ls
$ sudo mount /dev/sdb2 ./datadisk
mount: mount point ./datadisk does not exist
$ mkdir datadisk
$ sudo mount /dev/sdb2 ./datadisk
$

Acho confuso, pois ele sobrepõe o conteúdo existente no diretório. Existem dois conteúdos possíveis do diretório de ponto de montagem que podem ser alternados inesperadamente (para um usuário que não esteja executando a montagem).

Por que o mount não ocorre em um diretório recém-criado? É assim que os sistemas operacionais gráficos exibem mídia removível. Ficaria claro se o diretório está montado (existe) ou não montado (não existe). Tenho certeza de que há uma boa razão, mas ainda não consegui descobri-la.

    
por Melebius 23.12.2015 / 09:21

5 respostas

48

Este é um caso de um detalhe de implementação que vazou.

Em um sistema UNIX, cada diretório consiste em uma lista de nomes mapeados para os números inode . Um inode contém metadados que informam ao sistema se é um arquivo, diretório, dispositivo especial, pipe nomeado, etc. Se for um arquivo ou diretório, ele também informa ao sistema onde encontrar o conteúdo do arquivo ou diretório no disco. A maioria dos inodes são arquivos ou diretórios. A opção -i para ls listará os números de inode.

A montagem de um sistema de arquivos leva um diretório inode e define um sinalizador na cópia em memória do kernel para dizer "na verdade, ao procurar pelo conteúdo desse diretório, observe este outro sistema de arquivos" (veja o slide 10 de esta apresentação ). Isso é relativamente fácil, pois está mudando um único item de dados.

Por que não cria uma entrada de diretório para você apontando para o novo inode? Existem duas maneiras de implementar isso, ambas com desvantagens. Uma é escrever fisicamente um novo diretório no sistema de arquivos - mas isso falha se o sistema de arquivos for somente de leitura! O outro é adicionar a cada processo de listagem de diretórios uma lista de coisas "extras" que não estão realmente lá. Isso é complicado e potencialmente incorre em um pequeno impacto no desempenho de cada operação de arquivo.

Se você quiser pontos de montagem criados dinamicamente, o sistema automount pode fazer isso. Sistemas de arquivos especiais que não são de disco também podem criar diretórios à vontade, por ex. proc , sys , devfs e assim por diante.

Editar: veja também a resposta para O que acontece quando você 'monta sobre' uma pasta existente com conteúdo?

    
por 23.12.2015 / 13:12
19

Se mount(2) for necessário a criação de um novo diretório para ser o ponto de montagem, não será possível montar nada em um sistema de arquivos somente leitura. Isso seria estúpido, para que possamos descartar isso.

Se o mount opcionalmente criasse um novo diretório para ser o ponto de montagem, isso seria estranho. Não é como montar / desmontar acontecer o tempo todo, então colocar lógica extra no kernel para fazer essas duas etapas com uma única chamada de sistema não seria uma aceleração importante. Basta deixar o espaço do usuário para fazer uma chamada de sistema mkdir(2) , se quiser uma. A resposta de Dmitry aponta que ter mount(2) faz as duas coisas não serem atômicas. E você desejaria um argumento extra para mount(2) com sinalizadores de modo como open(2) , para O_CREAT , O_EXCL , etc. Seria apenas bobagem comparado a deixar o espaço do usuário fazer isso.

Ou talvez você esteja perguntando sobre ter o mount(8) (o programa tradicional que faz mount(2) de chamadas do sistema) fazer isso? Isso seria possível, mas já existe um mkdir(1) perfeitamente bom para o trabalho, e o design do Unix tem tudo a ver com boas ferramentas pequenas que podem ser combinadas. Se você quer uma ferramenta que faça as duas coisas, é fácil escrever um script de shell para construir essa ferramenta a partir de duas ferramentas mais simples. (Ou, como comentou muru, udisksctl já faz isso, então você não precisa escrevê-lo.) Além disso, o mount(8) normal do Linux do util-linux suporta mount -o x-mount.mkdir[=mode] usando a sintaxe x- para opções do userspace , em vez de opções a serem passadas para o sistema de arquivos.

Agora, a questão mais interessante: por que precisa haver um diretório no sistema de arquivos pai?

Como a resposta do pjc50 aponta (sem relação, mesmo que ele tenha minhas iniciais!), ter pontos de montagem exibidos nas listagens de diretórios exigiria uma verificação extra em cada readdir() .

Ter pontos de montagem como diretórios no diretório que os contém (no FS pai) é um truque legal. readdir() não precisa perceber que é um ponto de montagem. Isso só acontece se o ponto de montagem for usado como um componente de caminho. A resolução de caminho, é claro, precisa verificar a tabela de montagem para cada componente de diretório de um caminho.

    
por 23.12.2015 / 13:33
12

A montagem para o diretório existente faz uma chamada para mount praticamente atômica: ele é bem-sucedido ou falha, pelo menos da perspectiva do usuário. Se mount tivesse que criar o próprio ponto de montagem, ele teria dois pontos de falha, impossibilitando garantir uma reversão limpa. Imagine o seguinte cenário:

  1. mount cria com sucesso o ponto de montagem
  2. mount tenta montar um novo sistema de arquivos nesse diretório, mas falha
  3. mount tenta remover o ponto de montagem, mas falha

O sistema acaba com um efeito colateral de um mount com falha.

Aqui está outro:

  1. umount com sucesso desmonta um sistema de arquivos
  2. umount tenta remover o ponto de montagem, mas falha

Agora, o umount deve retornar sucesso ou falha?

    
por 23.12.2015 / 09:57
3

Outro caso que pode ocorrer:

Quando você inicializa, uma imagem somente de leitura básica é carregada no diretório raiz. Então você gostaria de substituí-lo quando você gostaria de montar uma raiz real. Então você pode imaginar que o syscall de montagem apenas troca o ro mountpoint para rw .

Aqui, vamos imaginar que você tenha um problema de sistema de arquivos no ponto de montagem raiz, você gostaria de poder repará-lo. Com a sobreposição de montagem, você pode desmontar o sistema de arquivos e usar fsck fornecido na imagem básica para resolvê-lo.

Esse recurso também pode ser útil em sistemas que precisam de segurança strong para acompanhar as alterações entre uma partição ro e um rw um.

    
por 23.12.2015 / 12:33
2

Eu sempre imaginei isso também.

Um wrapper simples como:

#!/bin/sh
eval "mkdir -p \"\$$#\"" 
/bin/mount "$@"  

salvo como um script executável chamado mount em um diretório que substitui /bin no seu PATH, deve cuidar disso se incomodar demais

(Antes de executar o binário mount real, ele cria um diretório com o nome do último argumento para mount , se esse diretório já não existir.)

Como alternativa, se você não quiser que as invocações com falha do wrapper mount criem diretórios, faça o seguinte:

#!/bin/sh
set -e
eval "lastArg=\"\$$#\""
test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; }
/bin/mount "$@"  ||  {  test -z "$madeDir" || rmdir "$lastArg"; }
    
por 23.12.2015 / 13:51

Tags