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
41 extern struct socket *socki_lookup(struct inode *inode);
42
43 #define _S(nr) (1<<((nr)-1))
44
45
46
47
48
49
50
51
52
53
54
55 static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
56 {
57 struct file *file;
58 struct inode *inode;
59 struct socket *sock;
60 unsigned short fs;
61 int result;
62 int xid;
63 int len;
64 select_table wait_table;
65 struct select_table_entry entry;
66 int (*select) (struct inode *, struct file *, int, select_table *);
67 int init_timeout, max_timeout;
68 int timeout;
69 int retrans;
70 int major_timeout_seen;
71 char *server_name;
72 int n;
73 int addrlen;
74 unsigned long old_mask;
75
76
77 int recv_xid;
78
79 xid = start[0];
80 len = ((char *) end) - ((char *) start);
81 file = server->file;
82 inode = file->f_inode;
83 select = file->f_op->select;
84 sock = socki_lookup(inode);
85 if (!sock) {
86 printk("nfs_rpc_call: socki_lookup failed\n");
87 return -EBADF;
88 }
89 init_timeout = server->timeo;
90 max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
91 retrans = server->retrans;
92 major_timeout_seen = 0;
93 server_name = server->hostname;
94 old_mask = current->blocked;
95 current->blocked |= ~(_S(SIGKILL)
96 #if 0
97 | _S(SIGSTOP)
98 #endif
99 | ((server->flags & NFS_MOUNT_INTR)
100 ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
101 ? _S(SIGINT) : 0)
102 | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
103 ? _S(SIGQUIT) : 0))
104 : 0));
105 fs = get_fs();
106 set_fs(get_ds());
107 for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
108 result = sock->ops->send(sock, (void *) start, len, 0, 0);
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