/proc/sys/fs/file-nr
Rev.1を表示中。最新版はこちら。
/proc/sys/fs/nr_openはプロセス毎の取得ファイルIDの最大値です。ファイルID取得は、0がら順に空きIDを走査して取得するので、結果的に最大取得数となります。ファイル管理は、このファイルIDをインデックスとするプロセスのfile[]にファイル構造体を設定する事で実装されます。このファイル構造体取得の最大値はfiles_stat.maxで、/proc/sys/fs/file-nrで取得でき、/proc/sys/fs/file-maxで更新できます。なお、CAP_SYS_ADMINケーパビリチィならファイル取得での/proc/sys/fs/file-maxの制約はありません。
[root@localhost ~]# cat /proc/sys/fs/nr_open 1048576 [root@localhost ~]# cat /proc/sys/fs/file-nr 1056 0 49739
static struct ctl_table root_table[] = {
{
.procname = "kernel",
.mode = 0555,
.child = kern_table,
},
{
.procname = "vm",
.mode = 0555,
.child = vm_table,
},
{
.procname = "fs",
.mode = 0555,
.child = fs_table,
},
{
.procname = "debug",
.mode = 0555,
.child = debug_table,
},
{
.procname = "dev",
.mode = 0555,
.child = dev_table,
},
{ }
};
static struct ctl_table fs_table[] = {
:
{
.procname = "file-nr",
.data = &files_stat,
.maxlen = sizeof(files_stat),
.mode = 0444, <- 4=100:読みのみ可
.proc_handler = proc_nr_files,
},
{
.procname = "file-max",
.data = &files_stat.max_files,
.maxlen = sizeof(files_stat.max_files),
.mode = 0644, <- 6=110:読み書き可
.proc_handler = proc_doulongvec_minmax,
},
:
}
int proc_nr_files(ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
files_stat.nr_files = get_nr_files();
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
}
static long get_nr_files(void)
{
return percpu_counter_read_positive(&nr_files);
}
static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
{
s64 ret = fbc->count;
barrier();
if (ret >= 0)
return ret;
return 0;
}
files_stat.max_filesのデフォルトは8192ですが、files_init()で取得するキャッシュメモリに応じたファイル数となります。nr_files/nr_free_filesはバージョン2での実装で、バージョン3では使用されません。
#define NR_FILE 8192
struct files_stat_struct files_stat;
struct files_stat_struct {
unsigned long nr_files;
unsigned long nr_free_files;
unsigned long max_files;
};
struct files_stat_struct files_stat = {
.max_files = NR_FILE
};
void __init files_init(unsigned long mempages)
{
unsigned long n;
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
n = (mempages * (PAGE_SIZE / 1024)) / 10;
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
files_defer_init();
lg_lock_init(files_lglock);
percpu_counter_init(&nr_files, 0);
}
補足
struct percpu_counter {
raw_spinlock_t lock;
s64 count;
#ifdef CONFIG_HOTPLUG_CPU
struct list_head list;
#endif
s32 __percpu *counters;
};
バージョン2ではファイル取得毎に、files_stat.nr_files++とし、/proc/sys/fs/nr_openは、それを取得する事で実装されていましたが、バージョン3では、パフォーマンス向上を目的とし、static struct percpu_counter nr_filesの32までは*counterにビット進数で設定され、それを超えれば countに*countersのビット進数でのファイル数を設定し、*counters=0とし、以降のファイル取得は、ビット進数の*countersのインクリメント(シフト)で、上記繰り返しの実装です。また、ファイルクローズはcountがデクリメントされ、ファイル数が32未満の時、countは0で、countは-1(0xffffffff)となってしまいます。従って、バージョン3での/proc/sys/fs/nr_openは、s32=32の範囲で誤差を有する事になります。マルチCPUでなくとも、厳密な実装としてfiles_stat.nr_files + (2進数)*files_stat.countersとすべきで、運営上となるとは考えられませんが、実装上の不手際でないかと・・・。なお、ファイル取得時のチェックは、そのような実装となっています。





