rsize和wsize决定了网络文件系统(NFS)一次网络交互所能够读写的数据块的大小,rsize和wsize的大小对网络文件系统(NFS)的性能有重要影响。rsize和wsize的大小是在用户配置的基础上客户端和服务器端共同协商的结果。
本文面向NFS的开发者和维护者,主要介绍rsize和wsize在客户端和服务器之间协商的流程,同时介绍rsize和wsize的设置的方法。文章以V3的实现为主线,顺便提及V4,代码基于linux-pnfs-2.6.32。
(1) 用户挂载
用户在挂载NFS文件系统的时候,可以用挂载选项指定rsize和wsize的大小,如下:
mount -t nfs -o vers=3,xxxx,rsize=????,wsize=????
Linux mount 命令将由系统调用下发到内核的vfs层,由vfs_kern_mount执行挂载操作。Vfs_kern_mount将调用具体文件系统的get_sb方法创建并初始化super block。对于NFS文件系统来说,这个方法便是Nfs_get_sb/Nfs4_get_sb,这两个函数定义在nfs模块代码的super.c文件当中。
(2) Nfs_get_sb/nfs4_get_sb
这里主要介绍nfs_get_sb,nfs4_get_sb可以以此为参照。Nfs_get_sb的部分函数代码如下:
2142 static int nfs_get_sb(structfile_system_type *fs_type,
2143 int flags, const char *dev_name, void*raw_data, struct vfsmount *mnt)
2144 {//其中raw_data包含了用户挂载时的挂载参数
2145 struct nfs_server *server = NULL;
2146 struct super_block *s;
2147 struct nfs_parsed_mount_data *data;//内核挂载参数
2148 struct nfs_fh *mntfh;
2149 struct dentry *mntroot;
2150 int (*compare_super)(structsuper_block *, void *) = nfs_compare_super;
2151 struct nfs_sb_mountdata sb_mntdata = {
2152 .mntflags = flags,
2153 };
2154 int error = -ENOMEM;
2155
2156 data = nfs_alloc_parsed_mount_data(3);//分配并且初始化内核挂载参数,此时data中的rsize和wsize分别被初始化为NFS_MAX_FILE_IO_SIZE(4U * 1048576U = 4MB);
2157 mntfh = kzalloc(sizeof(*mntfh),GFP_KERNEL);
2158 if (data == NULL || mntfh == NULL)
2159 goto out_free_fh;
2160
2161 security_init_mnt_opts(&data->lsm_opts);
2162
2163 /* Validate the mount data */
2164 error = nfs_validate_mount_data(raw_data,data, mntfh, dev_name);//利用raw_data和dev_name设置内核挂载参数,这时data当中rsize和wsize被设置为用户挂载时指定的大小。
2165 if (error < 0)
2166 goto out;
2167
2168 #ifdef CONFIG_NFS_V4
2169 if (data->version == 4) {
2170 error = nfs4_try_mount(flags,dev_name, data, mnt);
2171 kfree(data->client_address);
2172 goto out;
2173 }
2174 #endif /* CONFIG_NFS_V4 */
2175
2176 /* Get a volume representation */
2177 server = nfs_create_server(data,mntfh);//创建server,server中保存了和服务器交互的参数,在这个函数中客户端将和服务器协商rsize和wsize的大小。
2178 if (IS_ERR(server)) {