从mount -o一些理解结合cfs进行描述,窥探该项目全局。

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函数来完成的。

posted on 2014-03-13 20:13  ″ Jerry。  阅读(645)  评论(0编辑  收藏  举报