This source file includes following definitions.
- do_nfs_rpc_call
- nfs_rpc_call
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifdef MODULE
22 #include <linux/module.h>
23 #endif
24
25 #include <linux/sched.h>
26 #include <linux/nfs_fs.h>
27 #include <linux/errno.h>
28 #include <linux/socket.h>
29 #include <linux/fcntl.h>
30 #include <asm/segment.h>
31 #include <linux/in.h>
32 #include <linux/net.h>
33 #include <linux/mm.h>
34
35
36
37
38 #define NFS_SLACK_SPACE 1024
39
40 #define _S(nr) (1<<((nr)-1))
41
42
43
44
45
46
47
48
49
50
51
52 static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
53 {
54 struct file *file;
55 struct inode *inode;
56 struct socket *sock;
57 unsigned short fs;
58 int result;
59 int xid;
60 int len;
61 select_table wait_table;
62 struct select_table_entry entry;
63 int (*select) (struct inode *, struct file *, int, select_table *);
64 int init_timeout, max_timeout;
65 int timeout;
66 int retrans;
67 int major_timeout_seen;
68 char *server_name;
69 int n;
70 int addrlen;
71 unsigned long old_mask;
72
73
74 int recv_xid;
75
76 xid = start[0];
77 len = ((char *) end) - ((char *) start);
78 file = server->file;
79 inode = file->f_inode;
80 select = file->f_op->select;
81 sock = &inode->u.socket_i;
82 if (!sock) {
83 printk("nfs_rpc_call: socki_lookup failed\n");
84 return -EBADF;
85 }
86 init_timeout = server->timeo;
87 max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
88 retrans = server->retrans;
89 major_timeout_seen = 0;
90 server_name = server->hostname;
91 old_mask = current->blocked;
92 current->blocked |= ~(_S(SIGKILL)
93 #if 0
94 | _S(SIGSTOP)
95 #endif
96 | ((server->flags & NFS_MOUNT_INTR)
97 ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
98 ? _S(SIGINT) : 0)
99 | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
100 ? _S(SIGQUIT) : 0))
101 : 0));
102 fs = get_fs();
103 set_fs(get_ds());
104 for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
105
106
107 result = sock->ops->sendto(sock, (void *) start, len, 0, 0,
108 &(server->toaddr), sizeof((server->toaddr))) ;
109 if (result < 0) {
110 printk("nfs_rpc_call: send error = %d\n", result);
111 break;
112 }
113 re_select:
114 wait_table.nr = 0;
115 wait_table.entry = &entry;
116 current->state = TASK_INTERRUPTIBLE;
117 if (!select(inode, file, SEL_IN, &wait_table)
118 && !select(inode, file, SEL_IN, NULL)) {
119 if (timeout > max_timeout) {
120
121
122
123 printk("NFS max timeout reached on %s\n",
124 server_name);
125 timeout = max_timeout;
126 }
127 current->timeout = jiffies + timeout;
128 schedule();
129 remove_wait_queue(entry.wait_address, &entry.wait);
130 current->state = TASK_RUNNING;
131 if (current->signal & ~current->blocked) {
132 current->timeout = 0;
133 result = -ERESTARTSYS;
134 break;
135 }
136 if (!current->timeout) {
137 if (n < retrans)
138 continue;
139 if (server->flags & NFS_MOUNT_SOFT) {
140 printk("NFS server %s not responding, "
141 "timed out\n", server_name);
142 result = -EIO;
143 break;
144 }
145 n = 0;
146 timeout = init_timeout;
147 init_timeout <<= 1;
148 if (!major_timeout_seen) {
149 printk("NFS server %s not responding, "
150 "still trying\n", server_name);
151 }
152 major_timeout_seen = 1;
153 continue;
154 }
155 else
156 current->timeout = 0;
157 }
158 else if (wait_table.nr)
159 remove_wait_queue(entry.wait_address, &entry.wait);
160 current->state = TASK_RUNNING;
161 addrlen = 0;
162
163
164
165
166 result = sock->ops->recvfrom(sock, (void *)&recv_xid,
167 sizeof(recv_xid), 1, MSG_PEEK,
168 NULL, &addrlen);
169 if (result < 0) {
170 if (result == -EAGAIN) {
171 #if 0
172 printk("nfs_rpc_call: bad select ready\n");
173 #endif
174 goto re_select;
175 }
176 if (result == -ECONNREFUSED) {
177 #if 0
178 printk("nfs_rpc_call: server playing coy\n");
179 #endif
180 goto re_select;
181 }
182 if (result != -ERESTARTSYS) {
183 printk("nfs_rpc_call: recv error = %d\n",
184 -result);
185 }
186 break;
187 }
188 if (recv_xid == xid) {
189 if (major_timeout_seen)
190 printk("NFS server %s OK\n", server_name);
191 break;
192 }
193
194
195
196
197 (void)sock->ops->recvfrom(sock, (void *)&recv_xid,
198 sizeof(recv_xid), 1, 0, NULL,
199 &addrlen);
200 #if 0
201 printk("nfs_rpc_call: XID mismatch\n");
202 #endif
203 goto re_select;
204 }
205
206
207
208
209
210
211 result=sock->ops->recvfrom(sock, (void *)start,
212 size + 1024, 1, 0, NULL,
213
214 &addrlen);
215 if (result < 0) {
216 printk("NFS: notice message: result=%d\n", result);
217 } else if (result < addrlen) {
218 printk("NFS: just caught a too small read memory size..., email to NET channel\n");
219 printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
220 result = -EIO;
221 }
222 current->blocked = old_mask;
223 set_fs(fs);
224 return result;
225 }
226
227
228
229
230
231
232
233 int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
234 {
235 int result;
236
237 while (server->lock)
238 sleep_on(&server->wait);
239 server->lock = 1;
240 result = do_nfs_rpc_call(server, start, end, size);
241 server->lock = 0;
242 wake_up(&server->wait);
243 return result;
244 }
245