mount命令中除了常见的-t 也就是选择挂在文件系统的类型。还有一个重要的参数-o
这个参数里面可以携带很多参数,比如设定挂在的用户名,密码等等,但是这些参数怎么接受呢,也就是具体会传递到哪里呢?
首先注册文件系统的时候,有个数据结构file_system_type
如cfs的文件系统定义如下:
static struct file_system_type cfs_fs_type = {
.owner = THIS_MODULE, .name = "cfs", .get_sb = cfs_get_sb, .kill_sb = kill_litter_super, .fs_flags = 0,};这个参数是要传递给文件系统注册函数 register_filesystem(&cfs_file_system)的。
当我们调用mount的时候,一定会转到cfs_get_sb这个函数。
该函数调用cfs_fill_super(struct super_block *sb, void *data, int silent)
在这个函数中可以接收shell下传入的参数。
比如,在shell下有如下调用:
mount -t cfs -o mds=192.168.0.81 -o port=2123 -o user=$1 -o pwd=root -o semethod=$SEMETHOD seclient /mnt/cfs
那么在cfs_fill_super里面就有以下的命令解析:
while (ptr&&strlen(ptr))
{ if ((ptr2=strchr(ptr, ','))) { strncpy(opt, ptr, ptr2-ptr); opt[ptr2-ptr] = '\0'; ptr = ptr2+1; } else { strcpy(opt, ptr); ptr = '\0'; } if (!strncmp(opt, "user=", 5)) { memset(user,0,20); if(sscanf(opt, "user=%s", user)!=1){ TRACE_ERROR("malformed option \"%s\"\n", opt); goto failed_mount; } TRACE(TRACE_OFI, 0, "user=%s\n",user); } else if (!strncmp(opt, "pwd=", 4)) { memset(pwd,0,20); if(sscanf(opt, "pwd=%s", pwd)!=1){ TRACE_ERROR("malformed option \"%s\"\n", opt); goto failed_mount; } TRACE(TRACE_OFI, 0, "pwd=%s\n",pwd); } else if (!strncmp(opt, "mds=", 4)) { if (sscanf(opt, "mds=%s", mds_ip)!=1) { TRACE_ERROR("malformed option \"%s\"\n", opt); goto failed_mount; } TRACE(TRACE_OFI, 0, "mds ip=%s\n",mds_ip); } else if (!strncmp(opt, "port=", 5)) { if (sscanf(opt, "port=%d", &mds_port)!=1) { TRACE_ERROR("malformed option \"%s\"\n", opt); goto failed_mount; } TRACE(TRACE_OFI, 0, "mds port=%d\n",mds_port); } else if(!strncmp(opt, "semethod=", 9)){ if(sscanf(opt, "semethod=%d", &semeth)!=1) { TRACE_ERROR("malformed option \"%s\"\n", opt); goto failed_mount; } TRACE(TRACE_OFI, 0, "semethod=%d\n", semeth); } else { TRACE_ERROR("unknown option \"%s\"\n", opt); goto failed_mount; }(上面为非完整代码,待补充)
这里面就提取出来了下面的几个信息:MDS IP, 端口号,用户名,密码 ,安全模式等信息。
然后作为参数传递给 mds_login(mds_ip,mds_port,user,pwd).cfs_fill_super继续完成后面文件系统需要完成的东西。做安全的只是在这里做了上述改动。
当然mds_login()函数,在里面做了一些初始化,只要是做了一个iscsi通道的链接。这个链接当然需要用到 mds的IP地址,以及端口号,也就是网络的一个套接字。
然后调用login(user,pwd)这里只需要传递用户名和密码。
login函数,需要根据semeth也就是安全模式的不同,进行不同的初始化,比如某个模式需要调用client_sign函数来进行签名。其中里面做的很重要的一点就是把用户名,密码,角色,userid等信息都放在一个结构体,叫user_cmd然后传递给client_sign()函数进行签名。签名完成之后,条用函数send2server(&suer_cmd)传递给mds。
send2server函数。
send2server(struct mds_request *user_cmd)
该函数主要做了一下工作:
首先如果安全模式有要求的话,那么调用aes库进行加密。参数0,1分别代表加解密
加密后的东西放在cdb字符串中,然后调用信息发送命令将刚才的请求发送给mds
注意iscsi_socket_msg函数的第二个参数,如果是1表示发送信息,如果是0表示接受信息。
接受的信息依然是放在cdb缓冲区的。
然后如果上面的进行了加密过程的安全模式,那么这里是需要解密的。MDS是加密发送的,这边也是要解密的,总之是对应的关系。
里面很多细节处理,比如,如果是MDS_GETACL的话就调用print_acl来打印对应的acl表,
这里基本完成的命令有:首先 ./start user1这个是主要是mount,里面会把opcode设置为MDS_LOGIN。然后调用send2server完成mount操作。
如果是元数据请求的话,最后得到的就是元数据。
如果是./llx 查看访问控制列表,那么就到MDS拿到ACL表,然后打印。
如果是 ./chomodx 把命令传递过去,然后mds接到命令后,修改acl表。
因此主要的工作都是要通过 send2server函数来完成的。