symlinkの階層(procfs)
ブロックデバイスを有さないprocfsでは、シンボリックパス名をプロセスのnameidata.saved_names[MAX_NESTED_LINKS + 1]の設定による実装故に、シンボリックリンクは8階層までと思っていましたが、シンボリックパス名は、proc dentry毎のstruct proc_dir_entryのdata毎に動的にメモリを取得して設定されるようで、通常ファイルシステムと同じ40階層まででした。
[root@localhost lkm]# insmod proc_babakaka.ko
[root@localhost lkm]# dmesg
enum { MAX_NESTED_LINKS = 8 }; struct nameidata { struct path path; struct qstr last; struct path root; struct inode *inode; /* path.dentry.d_inode */ unsigned int flags; unsigned seq; int last_type; unsigned depth; char *saved_names[MAX_NESTED_LINKS + 1]; /* Intent data */ union { struct open_intent open; } intent; };[root@localhost lkm]# cat proc_babakaka.c
#include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> static int babakaka_show(struct seq_file *m, void *none) { seq_printf(m, "%s\n", "abcdefg"); return 0; } static int babakaka_open(struct inode *inode, struct file *file) { return single_open(file, babakaka_show, NULL); } static const struct file_operations babakaka_proc_fops = { .open = babakaka_open, .read = seq_read, }; static int __init proc_babakaka_init(void) { int i; char buf1[32], buf2[32]; proc_create("babakaka0", 0, NULL, &babakaka_proc_fops); printk("link start\n"); for (i = 0; i < 50; i++) { sprintf(buf1, "babakaka%d", i); sprintf(buf2, "babakaka%d", i + 1); if (!proc_symlink(buf2, NULL, buf1)) { printk("link err\n"); } } printk("link end\n"); return 0; } static void __exit proc_babakaka_exit(void) { int i; char buf1[32]; for (i = 0; i < 51; i++) { sprintf(buf1, "babakaka%d", i); remove_proc_entry(buf1, NULL); } } module_init(proc_babakaka_init); module_exit(proc_babakaka_exit);
[root@localhost lkm]# insmod proc_babakaka.ko
[root@localhost lkm]# dmesg
[ 5446.805708] link start [ 5446.807411] link end[root@localhost lkm]# cat /proc/babakaka0
abcdefg[root@localhost lkm]# cat /proc/babakaka40
abcdefg[root@localhost lkm]# cat /proc/babakaka41
cat: /proc/babakaka41: シンボリックリンクの階層が多すぎます
struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest) { struct proc_dir_entry *ent; ent = __proc_create(&parent, name, (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1); if (ent) { ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL); if (ent->data) { strcpy((char*)ent->data,dest); if (proc_register(parent, ent) < 0) { kfree(ent->data); kfree(ent); ent = NULL; } } else { kfree(ent); ent = NULL; } } return ent; } EXPORT_SYMBOL(proc_symlink);