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 #include <linux/config.h>
22 #include <linux/sched.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/errno.h>
25 #include <linux/socket.h>
26 #include <linux/fcntl.h>
27 #include <asm/segment.h>
28 #include <linux/in.h>
29 #include <linux/net.h>
30 #include <linux/mm.h>
31
32
33
34
35 #define NFS_SLACK_SPACE 1024
36
37
38 extern struct socket *socki_lookup(struct inode *inode);
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 = socki_lookup(inode);
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 result = sock->ops->send(sock, (void *) start, len, 0, 0);
106 if (result < 0) {
107 printk("nfs_rpc_call: send error = %d\n", result);
108 break;
109 }
110 re_select:
111 wait_table.nr = 0;
112 wait_table.entry = &entry;
113 current->state = TASK_INTERRUPTIBLE;
114 if (!select(inode, file, SEL_IN, &wait_table)
115 && !select(inode, file, SEL_IN, NULL)) {
116 if (timeout > max_timeout) {
117
118
119
120 printk("NFS max timeout reached on %s\n",
121 server_name);
122 timeout = max_timeout;
123 }
124 current->timeout = jiffies + timeout;
125 schedule();
126 remove_wait_queue(entry.wait_address, &entry.wait);
127 current->state = TASK_RUNNING;
128 if (current->signal & ~current->blocked) {
129 current->timeout = 0;
130 result = -ERESTARTSYS;
131 break;
132 }
133 if (!current->timeout) {
134 if (n < retrans)
135 continue;
136 if (server->flags & NFS_MOUNT_SOFT) {
137 printk("NFS server %s not responding, "
138 "timed out\n", server_name);
139 result = -EIO;
140 break;
141 }
142 n = 0;
143 timeout = init_timeout;
144 init_timeout <<= 1;
145 if (!major_timeout_seen) {
146 printk("NFS server %s not responding, "
147 "still trying\n", server_name);
148 }
149 major_timeout_seen = 1;
150 continue;
151 }
152 else
153 current->timeout = 0;
154 }
155 else if (wait_table.nr)
156 remove_wait_queue(entry.wait_address, &entry.wait);
157 current->state = TASK_RUNNING;
158 addrlen = 0;
159
160
161
162
163 result = sock->ops->recvfrom(sock, (void *)&recv_xid,
164 sizeof(recv_xid), 1, MSG_PEEK,
165 NULL, &addrlen);
166 if (result < 0) {
167 if (result == -EAGAIN) {
168 #if 0
169 printk("nfs_rpc_call: bad select ready\n");
170 #endif
171 goto re_select;
172 }
173 if (result == -ECONNREFUSED) {
174 #if 0
175 printk("nfs_rpc_call: server playing coy\n");
176 #endif
177 goto re_select;
178 }
179 if (result != -ERESTARTSYS) {
180 printk("nfs_rpc_call: recv error = %d\n",
181 -result);
182 }
183 break;
184 }
185 if (recv_xid == xid) {
186 if (major_timeout_seen)
187 printk("NFS server %s OK\n", server_name);
188 break;
189 }
190
191
192
193
194 (void)sock->ops->recvfrom(sock, (void *)&recv_xid,
195 sizeof(recv_xid), 1, 0, NULL,
196 &addrlen);
197 #if 0
198 printk("nfs_rpc_call: XID mismatch\n");
199 #endif
200 goto re_select;
201 }
202
203
204
205
206
207
208 result=sock->ops->recvfrom(sock, (void *)start,
209 size + 1024, 1, 0, NULL,
210
211 &addrlen);
212 if (result < 0) {
213 printk("NFS: notice message: result=%d\n", result);
214 } else if (result < addrlen) {
215 printk("NFS: just caught a too small read memory size..., email to NET channel\n");
216 printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
217 result = -EIO;
218 }
219 current->blocked = old_mask;
220 set_fs(fs);
221 return result;
222 }
223
224
225
226
227
228
229
230 int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
231 {
232 int result;
233
234 while (server->lock)
235 sleep_on(&server->wait);
236 server->lock = 1;
237 result = do_nfs_rpc_call(server, start, end, size);
238 server->lock = 0;
239 wake_up(&server->wait);
240 return result;
241 }
242