4 * Copyright (C) 2000, Charles Loep / Corel Corp.
5 * Copyright (C) 2001, Urban Widmark
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/file.h>
17 #include <linux/dcache.h>
18 #include <linux/module.h>
19 #include <linux/net.h>
20 #include <linux/kthread.h>
23 #include <asm/system.h>
24 #include <asm/uaccess.h>
28 #include "smb_mount.h"
29 #include "smb_debug.h"
39 static enum smbiod_state smbiod_state
= SMBIOD_DEAD
;
40 static struct task_struct
*smbiod_thread
;
41 static DECLARE_WAIT_QUEUE_HEAD(smbiod_wait
);
42 static LIST_HEAD(smb_servers
);
43 static DEFINE_SPINLOCK(servers_lock
);
45 #define SMBIOD_DATA_READY (1<<0)
46 static unsigned long smbiod_flags
;
48 static int smbiod(void *);
49 static int smbiod_start(void);
52 * called when there's work for us to do
54 void smbiod_wake_up(void)
56 if (smbiod_state
== SMBIOD_DEAD
)
58 set_bit(SMBIOD_DATA_READY
, &smbiod_flags
);
59 wake_up_interruptible(&smbiod_wait
);
63 * start smbiod if none is running
65 static int smbiod_start(void)
67 struct task_struct
*tsk
;
70 if (smbiod_state
!= SMBIOD_DEAD
)
72 smbiod_state
= SMBIOD_STARTING
;
73 __module_get(THIS_MODULE
);
74 spin_unlock(&servers_lock
);
75 tsk
= kthread_run(smbiod
, NULL
, "smbiod");
78 module_put(THIS_MODULE
);
81 spin_lock(&servers_lock
);
83 smbiod_state
= SMBIOD_DEAD
;
86 smbiod_state
= SMBIOD_RUNNING
;
93 * register a server & start smbiod if necessary
95 int smbiod_register_server(struct smb_sb_info
*server
)
98 spin_lock(&servers_lock
);
99 list_add(&server
->entry
, &smb_servers
);
100 VERBOSE("%p\n", server
);
101 ret
= smbiod_start();
102 spin_unlock(&servers_lock
);
107 * Unregister a server
108 * Must be called with the server lock held.
110 void smbiod_unregister_server(struct smb_sb_info
*server
)
112 spin_lock(&servers_lock
);
113 list_del_init(&server
->entry
);
114 VERBOSE("%p\n", server
);
115 spin_unlock(&servers_lock
);
118 smbiod_flush(server
);
121 void smbiod_flush(struct smb_sb_info
*server
)
123 struct list_head
*tmp
, *n
;
124 struct smb_request
*req
;
126 list_for_each_safe(tmp
, n
, &server
->xmitq
) {
127 req
= list_entry(tmp
, struct smb_request
, rq_queue
);
128 req
->rq_errno
= -EIO
;
129 list_del_init(&req
->rq_queue
);
131 wake_up_interruptible(&req
->rq_wait
);
133 list_for_each_safe(tmp
, n
, &server
->recvq
) {
134 req
= list_entry(tmp
, struct smb_request
, rq_queue
);
135 req
->rq_errno
= -EIO
;
136 list_del_init(&req
->rq_queue
);
138 wake_up_interruptible(&req
->rq_wait
);
143 * Wake up smbmount and make it reconnect to the server.
144 * This must be called with the server locked.
146 * FIXME: add smbconnect version to this
148 int smbiod_retry(struct smb_sb_info
*server
)
150 struct list_head
*head
;
151 struct smb_request
*req
;
152 struct pid
*pid
= get_pid(server
->conn_pid
);
155 VERBOSE("state: %d\n", server
->state
);
156 if (server
->state
== CONN_VALID
|| server
->state
== CONN_RETRYING
)
159 smb_invalidate_inodes(server
);
162 * Some requests are meaningless after a retry, so we abort them.
163 * One example are all requests using 'fileid' since the files are
166 head
= server
->xmitq
.next
;
167 while (head
!= &server
->xmitq
) {
168 req
= list_entry(head
, struct smb_request
, rq_queue
);
171 req
->rq_bytes_sent
= 0;
172 if (req
->rq_flags
& SMB_REQ_NORETRY
) {
173 VERBOSE("aborting request %p on xmitq\n", req
);
174 req
->rq_errno
= -EIO
;
175 list_del_init(&req
->rq_queue
);
177 wake_up_interruptible(&req
->rq_wait
);
182 * FIXME: test the code for retrying request we already sent
184 head
= server
->recvq
.next
;
185 while (head
!= &server
->recvq
) {
186 req
= list_entry(head
, struct smb_request
, rq_queue
);
189 if (req
->rq_flags
& SMB_REQ_RETRY
) {
190 /* must move the request to the xmitq */
191 VERBOSE("retrying request %p on recvq\n", req
);
192 list_move(&req
->rq_queue
, &server
->xmitq
);
197 VERBOSE("aborting request %p on recvq\n", req
);
198 /* req->rq_rcls = ???; */ /* FIXME: set smb error code too? */
199 req
->rq_errno
= -EIO
;
200 list_del_init(&req
->rq_queue
);
202 wake_up_interruptible(&req
->rq_wait
);
205 smb_close_socket(server
);
208 /* FIXME: this is fatal, umount? */
209 printk(KERN_ERR
"smb_retry: no connection process\n");
210 server
->state
= CONN_RETRIED
;
215 * Change state so that only one retry per server will be started.
217 server
->state
= CONN_RETRYING
;
220 * Note: use the "priv" flag, as a user process may need to reconnect.
222 result
= kill_pid(pid
, SIGUSR1
, 1);
224 /* FIXME: this is most likely fatal, umount? */
225 printk(KERN_ERR
"smb_retry: signal failed [%d]\n", result
);
228 VERBOSE("signalled pid %d\n", pid_nr(pid
));
230 /* FIXME: The retried requests should perhaps get a "time boost". */
238 * Currently handles lockingX packets.
240 static void smbiod_handle_request(struct smb_sb_info
*server
)
242 PARANOIA("smbiod got a request ... and we don't implement oplocks!\n");
243 server
->rstate
= SMB_RECV_DROP
;
247 * Do some IO for one server.
249 static void smbiod_doio(struct smb_sb_info
*server
)
254 if (server
->state
!= CONN_VALID
)
258 result
= smb_request_recv(server
);
260 server
->state
= CONN_INVALID
;
261 smbiod_retry(server
);
262 goto out
; /* reconnecting is slow */
263 } else if (server
->rstate
== SMB_RECV_REQUEST
)
264 smbiod_handle_request(server
);
265 } while (result
> 0 && maxwork
-- > 0);
268 * If there is more to read then we want to be sure to wake up again.
270 if (server
->state
!= CONN_VALID
)
272 if (smb_recv_available(server
) > 0)
273 set_bit(SMBIOD_DATA_READY
, &smbiod_flags
);
276 result
= smb_request_send_server(server
);
278 server
->state
= CONN_INVALID
;
279 smbiod_retry(server
);
280 goto out
; /* reconnecting is slow */
282 } while (result
> 0);
285 * If the last request was not sent out we want to wake up again.
287 if (!list_empty(&server
->xmitq
))
288 set_bit(SMBIOD_DATA_READY
, &smbiod_flags
);
295 * smbiod kernel thread
297 static int smbiod(void *unused
)
299 VERBOSE("SMB Kernel thread starting (%d) ...\n", current
->pid
);
302 struct smb_sb_info
*server
;
303 struct list_head
*pos
, *n
;
305 /* FIXME: Use poll? */
306 wait_event_interruptible(smbiod_wait
,
307 test_bit(SMBIOD_DATA_READY
, &smbiod_flags
));
308 if (signal_pending(current
)) {
309 spin_lock(&servers_lock
);
310 smbiod_state
= SMBIOD_DEAD
;
311 spin_unlock(&servers_lock
);
315 clear_bit(SMBIOD_DATA_READY
, &smbiod_flags
);
317 spin_lock(&servers_lock
);
318 if (list_empty(&smb_servers
)) {
319 smbiod_state
= SMBIOD_DEAD
;
320 spin_unlock(&servers_lock
);
324 list_for_each_safe(pos
, n
, &smb_servers
) {
325 server
= list_entry(pos
, struct smb_sb_info
, entry
);
326 VERBOSE("checking server %p\n", server
);
328 if (server
->state
== CONN_VALID
) {
329 spin_unlock(&servers_lock
);
331 smb_lock_server(server
);
333 smb_unlock_server(server
);
335 spin_lock(&servers_lock
);
338 spin_unlock(&servers_lock
);
341 VERBOSE("SMB Kernel thread exiting (%d) ...\n", current
->pid
);
342 module_put_and_exit(0);