無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

/proc/sys/fs/file-nr


/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とすべきで、運営上問題となるとは考えられませんが、実装上の不手際でないかと・・・。なお、ファイル取得時のチェックは、そのような実装となっています。


最終更新 2016/08/30 17:51:43 - north
(2016/08/30 17:42:34 作成)