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