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