symlinkの階層(procfs)
Rev.1を表示中。最新版はこちら。
ブロックデバイスを有さないprocfsでは、シンボリックパス名をプロセスのnameidata.saved_names[MAX_NESTED_LINKS + 1]の設定による実装故に、シンボリックリンクは8階層までと思っていましたが、シンボリックパス名は、proc dentry毎のstruct proc_dir_entryのdata毎に動的にメモリを取得して設定されるようで、通常ファイルシステムと同じ40階層まででした。
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 cmdline_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, &cmdline_proc_fops);
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");
}
}
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]# 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);





