Come descritto nel log di commit del kernel linkato da jiliagre sopra, il file nsfs
filesystem è un filesystem virtuale che rende disponibili gli spazi dei nomi del kernel Linux. È separato da /proc
filesystem "proc", dove alcune voci della directory dei processi fanno riferimento agli inode nel nsfs
filesystem per mostrare quali spazi dei nomi un certo processo (o thread) sta attualmente utilizzando.
Il nsfs
non viene elencato in /proc/filesystems
(mentre proc
does), quindi non può essere montato in modo esplicito. mount -t nsfs ./namespaces
fallisce con "tipo di filesystem sconosciuto". Questo è, come nsfs
poiché è strettamente intrecciato con l'proc
filesystem.
Il tipo di filesystem nsfs
diventa visibile solo tramite /proc/$PID/mountinfo
quando si esegue il bind-mount di un collegamento al filesystem dello spazio dei nomi esistente (!) su un altro target. Come suggerisce giustamente Stephen Kitt sopra, questo serve a mantenere gli spazi dei nomi esistenti anche se nessun processo li utilizza più.
Ad esempio, crea un nuovo spazio dei nomi utente con un nuovo spazio dei nomi di rete, quindi esegui il bind-mount, quindi esci:lo spazio dei nomi esiste ancora, ma lsns
non lo troverà, dato che non è elencato in /proc/$PID/ns
più, ma esiste come punto di montaggio (bind).
# bind mount only needs an inode, not necessarily a directory ;)
touch mynetns
# create new network namespace, show its id and then bind-mount it, so it
# is kept existing after the unshare'd bash has terminated.
# output: net:[##########]
NS=$(sudo unshare -n bash -c "readlink /proc/self/ns/net && mount --bind /proc/self/ns/net mynetns") && echo $NS
# notice how lsns cannot see this namespace anymore: no match!
lsns -t net | grep ${NS:5:-1} || echo "lsns: no match for net:[${NS:5:-1}]"
# however, findmnt does locate it on the nsfs...
findmnt -t nsfs | grep ${NS:5:-1} || echo "no match for net:[${NS:5:-1}]"
# output: /home/.../mynetns nsfs[net:[##########]] nsfs rw
# let the namespace go...
echo "unbinding + releasing network namespace"
sudo umount mynetns
findmnt -t nsfs | grep ${NS:5:-1} || echo "findmnt: no match for net:[${NS:5:-1}]"
# clean up
rm mynetns
L'output dovrebbe essere simile a questo:
net:[4026532992]
lsns: no match for net:[4026532992]
/home/.../mynetns nsfs[net:[4026532992]] nsfs rw
unbinding + releasing network namespace
findmnt: no match for net:[4026532992]
Si prega di notare che non è possibile creare spazi dei nomi tramite il filesystem nsfs, solo tramite syscalls clone() (CLONE_NEW...
) e annulla la condivisione. Il nsfs
riflette solo lo stato attuale del kernel w.r.t. namespace, ma non può crearli o distruggerli.
Gli spazi dei nomi vengono automaticamente distrutti ogni volta che non rimane alcun riferimento ad essi, nessun processo (quindi nessun /proc/$PID/ns/...
) E nemmeno bind-mount, come abbiamo visto nell'esempio precedente.
Questo è il "Name Space File System", usato dal setns
chiamata di sistema e, come mostra il suo codice sorgente, ioctl relativi allo spazio dei nomi (ad es. NS_GET_USERNS
, NS_GET_OWNER_UID
...)
NSFS
voci di pseudo-file erano fornite dal /proc
file system fino a Linux 3.19. Ecco il commit di questa modifica.
Vedi il commento di Stephen Kitt su una possibile spiegazione sulla presenza di questo file.