Linux와 FreeBSD 환경에서 동작하는 C언어 기반의 NFSv4 Mount 함수를 정리한다.
1. Linux NFSv4 Mount 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int linux_mount_nfs4(char *mount_point, char *server_ip, char *server_path)
{
int result;
char tmp_server_path[128] = {'\0',};
char tmp_option[128] = {'\0',};
strcpy(tmp_server_path, ":");
strcat(tmp_server_path, server_path);
strcpy(tmp_option, "nolock,addr=");
strcat(tmp_option, server_ip);
result = mount(tmp_server_path, mount_point, "nfs4", 0, tmp_option);
if(result == 0)
return 1;
else
return -1;
}
[Code 1]은 Linux 환경에서 mount() 함수를 이용하여 NFSv4 Mount를 수행하는 함수이다. 리눅스 Man Page에도 mount() 함수를 이용한 NFSv4 Mount 수행 방법이 나와있지 않다.
2. FreeBSD NFSv4 Mount 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
int linux_mount_nfs4(char *mount_point, char *server_ip, char *server_path)
static void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len)
{
int i;
if (*iovlen < 0)
return;
i = *iovlen;
*iov = realloc(*iov, sizeof(**iov) * (i + 2));
if (*iov == NULL) {
*iovlen = -1;
return;
}
(*iov)[i].iov_base = strdup(name);
(*iov)[i].iov_len = strlen(name) + 1;
i++;
(*iov)[i].iov_base = val;
if (len == (size_t)-1) {
if (val != NULL)
len = strlen(val) + 1;
else
len = 0;
}
(*iov)[i].iov_len = (int)len;
*iovlen = ++i;
}
static void clean_iovec(struct iovec *iov, int iovlen){
int i;
for(i = iovlen-2; i >= 0; i=-2)
free(iov[i].iov_base);
free(iov);
}
static int freebsd_mount_nfs4(char *mount_point, char *server_ip, char *server_path)
{
CLIENT *clp;
struct iovec *iov = NULL;
struct addrinfo hints, *ai_nfs;
struct sockaddr *addr;
struct netconfig *nconf;
struct netbuf nfs_nb;
char errmsg[] = "NFSv4 Mount Error!";
char hostname[128];
char *netid;
int iovlen = 0;
int addrlen = 0;
int result;
// Get network info
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_socktype = SOCK_STREAM;
if(getaddrinfo(server_ip, "2049", NULL, &ai_nfs) != 0)
return -1;
// Check working of NFSv4 server.
nfs_nb.buf = ai_nfs->ai_addr;
nfs_nb.len = ai_nfs->ai_addrlen;
nconf = getnetconfigent("tcp");
clp = clnt_tli_create(RPC_ANYFD, nconf, &nfs_nb, NFS_PROGRAM, 4, 0, 0);
if(clp == NULL)
return -1;
clnt_destroy(clp);
// Set parameters
sprintf(hostname,"%s:%s", server_ip, server_path);
build_iovec(&iov, &iovlen, "hostname", hostname, (size_t)-1);
build_iovec(&iov, &iovlen, "addr", ai_nfs->ai_addr, ai_nfs->ai_addrlen);
build_iovec(&iov, &iovlen, "dirpath", server_path, (size_t)-1);
build_iovec(&iov, &iovlen, "fstype", "nfs", (size_t)-1);
build_iovec(&iov, &iovlen, "nfsv4", NULL, 0);
build_iovec(&iov, &iovlen, "fspath", mount_point, (size_t)-1);
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
// Mount
result = nmount(iov, iovlen, 0);
clean_iovec(iov, iovlen);
freeaddrinfo(ai_nfs);
if(result == 0)
return 1;
else
return -1;
}
[Code 2]는 FreeBSD 환경에서 mount() 함수를 이용하여 NFSv4 Mount를 수행하는 함수이다. FreeBSD의 mount_nfs Tool을 참고하여 제작하였다. 57 줄에서 NFSv4 서버 상태를 점검 하였을때는 NFSv4 서버의 동작이 문제 없다가, 78 줄에서 nmount() 함수 수행 시 NFSv4 서버에 문제가 생기면 nmount() 함수에서 Blocking 되는 문제가 발생한다.