2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/fsnotify.h>
17 #include <linux/jhash.h>
19 #include <linux/in6.h>
20 #include <linux/kthread.h>
21 #include <linux/pagemap.h>
22 #include <linux/poll.h>
23 #include <linux/slab.h>
24 #include <linux/swap.h>
25 #include <linux/syscalls.h>
26 #include <linux/vmalloc.h>
31 * Async machinery lives here.
32 * All commands being sent to server do _not_ require sync reply,
33 * instead, if it is really needed, like readdir or readpage, caller
34 * sleeps waiting for data, which will be placed into provided buffer
35 * and caller will be awakened.
37 * Every command response can come without some listener. For example
38 * readdir response will add new objects into cache without appropriate
39 * request from userspace. This is used in cache coherency.
41 * If object is not found for given data, it is discarded.
43 * All requests are received by dedicated kernel thread.
47 * Basic network sending/receiving functions.
48 * Blocked mode is used.
50 static int netfs_data_recv(struct netfs_state
*st
, void *buf
, u64 size
)
61 msg
.msg_iov
= (struct iovec
*)&iov
;
65 msg
.msg_control
= NULL
;
66 msg
.msg_controllen
= 0;
67 msg
.msg_flags
= MSG_DONTWAIT
;
69 err
= kernel_recvmsg(st
->socket
, &msg
, &iov
, 1, iov
.iov_len
,
72 printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__
, size
, err
);
80 static int pohmelfs_data_recv(struct netfs_state
*st
, void *data
, unsigned int size
)
82 unsigned int revents
= 0;
83 unsigned int err_mask
= POLLERR
| POLLHUP
| POLLRDHUP
;
84 unsigned int mask
= err_mask
| POLLIN
;
87 while (size
&& !err
) {
88 revents
= netfs_state_poll(st
);
90 if (!(revents
& mask
)) {
94 prepare_to_wait(&st
->thread_wait
, &wait
, TASK_INTERRUPTIBLE
);
95 if (kthread_should_stop())
98 revents
= netfs_state_poll(st
);
103 if (signal_pending(current
))
109 finish_wait(&st
->thread_wait
, &wait
);
113 netfs_state_lock(st
);
114 if (st
->socket
&& (st
->read_socket
== st
->socket
) && (revents
& POLLIN
)) {
115 err
= netfs_data_recv(st
, data
, size
);
124 if (revents
& err_mask
) {
125 printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
126 __func__
, revents
, st
->socket
, size
, err
);
129 netfs_state_unlock(st
);
132 if (netfs_state_trylock_send(st
)) {
133 netfs_state_exit(st
);
134 err
= netfs_state_init(st
);
137 netfs_state_unlock_send(st
);
143 if (kthread_should_stop())
147 printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
148 "should_stop: %d, size: %u, err: %d.\n",
149 __func__
, st
->socket
, st
->read_socket
,
150 revents
, revents
& err_mask
, kthread_should_stop(), size
, err
);
156 int pohmelfs_data_recv_and_check(struct netfs_state
*st
, void *data
, unsigned int size
)
158 struct netfs_cmd
*cmd
= &st
->cmd
;
161 err
= pohmelfs_data_recv(st
, data
, size
);
165 return pohmelfs_crypto_process_input_data(&st
->eng
, cmd
->iv
, data
, NULL
, size
);
172 struct netfs_poll_helper
{
174 struct netfs_state
*st
;
177 static int netfs_queue_wake(wait_queue_t
*wait
, unsigned mode
, int sync
, void *key
)
179 struct netfs_state
*st
= container_of(wait
, struct netfs_state
, wait
);
181 wake_up(&st
->thread_wait
);
185 static void netfs_queue_func(struct file
*file
, wait_queue_head_t
*whead
,
188 struct netfs_state
*st
= container_of(pt
, struct netfs_poll_helper
, pt
)->st
;
191 init_waitqueue_func_entry(&st
->wait
, netfs_queue_wake
);
192 add_wait_queue(whead
, &st
->wait
);
195 static void netfs_poll_exit(struct netfs_state
*st
)
198 remove_wait_queue(st
->whead
, &st
->wait
);
203 static int netfs_poll_init(struct netfs_state
*st
)
205 struct netfs_poll_helper ph
;
208 init_poll_funcptr(&ph
.pt
, &netfs_queue_func
);
210 st
->socket
->ops
->poll(NULL
, st
->socket
, &ph
.pt
);
215 * Get response for readpage command. We search inode and page in its mapping
216 * and copy data into. If it was async request, then we queue page into shared
217 * data and wakeup listener, who will copy it to userspace.
219 * There is a work in progress of allowing to call copy_to_user() directly from
220 * async receiving kernel thread.
222 static int pohmelfs_read_page_response(struct netfs_state
*st
)
224 struct pohmelfs_sb
*psb
= st
->psb
;
225 struct netfs_cmd
*cmd
= &st
->cmd
;
230 if (cmd
->size
> PAGE_CACHE_SIZE
) {
235 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
237 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
242 page
= find_get_page(inode
->i_mapping
, cmd
->start
>> PAGE_CACHE_SHIFT
);
243 if (!page
|| !PageLocked(page
)) {
244 printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n",
245 __func__
, page
, cmd
->id
, cmd
->start
, cmd
->start
>> PAGE_CACHE_SHIFT
);
248 unsigned int sz
= min(cmd
->size
, st
->size
);
250 err
= pohmelfs_data_recv(st
, st
->data
, sz
);
259 goto err_out_page_put
;
267 err
= pohmelfs_data_recv(st
, addr
, cmd
->size
);
271 goto err_out_page_unlock
;
274 dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n",
275 __func__
, page
, cmd
->start
, cmd
->size
, PageLocked(page
));
277 SetPageChecked(page
);
278 if ((psb
->hash_string
|| psb
->cipher_string
) && psb
->perform_crypto
&& cmd
->size
) {
279 err
= pohmelfs_crypto_process_input_page(&st
->eng
, page
, cmd
->size
, cmd
->iv
);
281 goto err_out_page_unlock
;
283 SetPageUptodate(page
);
285 page_cache_release(page
);
288 pohmelfs_put_inode(POHMELFS_I(inode
));
289 wake_up(&st
->psb
->wait
);
297 page_cache_release(page
);
299 pohmelfs_put_inode(POHMELFS_I(inode
));
301 wake_up(&st
->psb
->wait
);
305 static int pohmelfs_check_name(struct pohmelfs_inode
*parent
, struct qstr
*str
,
306 struct netfs_inode_info
*info
)
309 struct pohmelfs_name
*n
;
313 mutex_lock(&parent
->offset_lock
);
314 n
= pohmelfs_search_hash(parent
, str
->hash
);
317 mutex_unlock(&parent
->offset_lock
);
322 inode
= ilookup(parent
->vfs_inode
.i_sb
, ino
);
326 dprintk("%s: parent: %llu, inode: %llu.\n", __func__
, parent
->ino
, ino
);
328 pohmelfs_fill_inode(inode
, info
);
329 pohmelfs_put_inode(POHMELFS_I(inode
));
336 * Readdir response from server. If special field is set, we wakeup
337 * listener (readdir() call), which will copy data to userspace.
339 static int pohmelfs_readdir_response(struct netfs_state
*st
)
342 struct netfs_cmd
*cmd
= &st
->cmd
;
343 struct netfs_inode_info
*info
;
344 struct pohmelfs_inode
*parent
= NULL
, *npi
;
345 int err
= 0, last
= cmd
->ext
;
348 if (cmd
->size
> st
->size
)
351 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
353 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
356 parent
= POHMELFS_I(inode
);
358 if (!cmd
->size
&& cmd
->start
) {
366 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
370 info
= (struct netfs_inode_info
*)(st
->data
);
372 name
= (char *)(info
+ 1);
373 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
376 str
.hash
= jhash(str
.name
, str
.len
, 0);
378 netfs_convert_inode_info(info
);
381 err
= pohmelfs_check_name(parent
, &str
, info
);
389 info
->ino
= cmd
->start
;
391 info
->ino
= pohmelfs_new_ino(st
->psb
);
393 dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n",
394 __func__
, parent
->ino
, info
->ino
, str
.name
, str
.hash
, str
.len
,
397 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
404 struct dentry
*dentry
, *alias
, *pd
;
406 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
407 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
409 pd
= d_find_alias(&parent
->vfs_inode
);
411 str
.hash
= full_name_hash(str
.name
, str
.len
);
412 dentry
= d_alloc(pd
, &str
);
414 alias
= d_materialise_unique(dentry
, &npi
->vfs_inode
);
426 set_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
427 set_bit(NETFS_INODE_REMOTE_SYNCED
, &parent
->state
);
428 wake_up(&st
->psb
->wait
);
430 pohmelfs_put_inode(parent
);
435 clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
);
436 printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__
, parent
->ino
, cmd
->start
, cmd
->id
);
437 pohmelfs_put_inode(parent
);
438 wake_up(&st
->psb
->wait
);
443 * Lookup command response.
444 * It searches for inode to be looked at (if it exists) and substitutes
445 * its inode information (size, permission, mode and so on), if inode does
446 * not exist, new one will be created and inserted into caches.
448 static int pohmelfs_lookup_response(struct netfs_state
*st
)
450 struct inode
*inode
= NULL
;
451 struct netfs_cmd
*cmd
= &st
->cmd
;
452 struct netfs_inode_info
*info
;
453 struct pohmelfs_inode
*parent
= NULL
, *npi
;
457 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
459 printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n",
460 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
464 parent
= POHMELFS_I(inode
);
471 if (cmd
->size
< sizeof(struct netfs_inode_info
)) {
472 printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n",
473 __func__
, cmd
->id
, cmd
->start
, cmd
->size
);
478 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
482 info
= (struct netfs_inode_info
*)(st
->data
);
483 name
= (char *)(info
+ 1);
485 netfs_convert_inode_info(info
);
487 info
->ino
= cmd
->start
;
489 info
->ino
= pohmelfs_new_ino(st
->psb
);
491 dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n",
492 __func__
, parent
->ino
, info
->ino
, name
, cmd
->start
);
495 npi
= pohmelfs_new_inode(st
->psb
, parent
, NULL
, info
, 0);
500 str
.len
= cmd
->size
- sizeof(struct netfs_inode_info
) - 1 - cmd
->cpad
;
501 str
.hash
= jhash(name
, str
.len
, 0);
503 npi
= pohmelfs_new_inode(st
->psb
, parent
, &str
, info
, 0);
511 set_bit(NETFS_INODE_REMOTE_SYNCED
, &npi
->state
);
512 clear_bit(NETFS_INODE_OWNED
, &npi
->state
);
515 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
516 pohmelfs_put_inode(parent
);
518 wake_up(&st
->psb
->wait
);
523 pohmelfs_put_inode(parent
);
525 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
526 wake_up(&st
->psb
->wait
);
527 printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n",
528 __func__
, inode
, cmd
->id
, cmd
->start
, cmd
->size
, err
);
533 * Create response, just marks local inode as 'created', so that writeback
534 * for any of its children (or own) would not try to sync it again.
536 static int pohmelfs_create_response(struct netfs_state
*st
)
539 struct netfs_cmd
*cmd
= &st
->cmd
;
540 struct pohmelfs_inode
*pi
;
542 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
544 printk("%s: failed to find inode: id: %llu, start: %llu.\n",
545 __func__
, cmd
->id
, cmd
->start
);
549 pi
= POHMELFS_I(inode
);
552 * To lock or not to lock?
553 * We actually do not care if it races...
556 make_bad_inode(inode
);
557 set_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
559 pohmelfs_put_inode(pi
);
561 wake_up(&st
->psb
->wait
);
565 wake_up(&st
->psb
->wait
);
570 * Object remove response. Just says that remove request has been received.
571 * Used in cache coherency protocol.
573 static int pohmelfs_remove_response(struct netfs_state
*st
)
575 struct netfs_cmd
*cmd
= &st
->cmd
;
578 err
= pohmelfs_data_recv_and_check(st
, st
->data
, cmd
->size
);
582 dprintk("%s: parent: %llu, path: '%s'.\n", __func__
, cmd
->id
, (char *)st
->data
);
588 * Transaction reply processing.
590 * Find transaction based on its generation number, bump its reference counter,
591 * so that none could free it under us, drop from the trees and lists and
592 * drop reference counter. When it hits zero (when all destinations replied
593 * and all timeout handled by async scanning code), completion will be called
594 * and transaction will be freed.
596 static int pohmelfs_transaction_response(struct netfs_state
*st
)
598 struct netfs_trans_dst
*dst
;
599 struct netfs_trans
*t
= NULL
;
600 struct netfs_cmd
*cmd
= &st
->cmd
;
601 short err
= (signed)cmd
->ext
;
603 mutex_lock(&st
->trans_lock
);
604 dst
= netfs_trans_search(st
, cmd
->start
);
606 netfs_trans_remove_nolock(dst
, st
);
609 mutex_unlock(&st
->trans_lock
);
612 printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n",
613 __func__
, cmd
->start
, cmd
->id
, cmd
->size
, cmd
->ext
);
619 netfs_trans_drop_dst_nostate(dst
);
622 wake_up(&st
->psb
->wait
);
627 * Inode metadata cache coherency message.
629 static int pohmelfs_page_cache_response(struct netfs_state
*st
)
631 struct netfs_cmd
*cmd
= &st
->cmd
;
634 dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__
, st
, cmd
->id
, cmd
->start
, cmd
->size
);
636 inode
= ilookup(st
->psb
->sb
, cmd
->id
);
638 printk("%s: failed to find inode: id: %llu.\n", __func__
, cmd
->id
);
642 set_bit(NETFS_INODE_NEED_FLUSH
, &POHMELFS_I(inode
)->state
);
643 pohmelfs_put_inode(POHMELFS_I(inode
));
649 * Root capabilities response: export statistics
650 * like used and available size, number of files and dirs,
653 static int pohmelfs_root_cap_response(struct netfs_state
*st
)
655 struct netfs_cmd
*cmd
= &st
->cmd
;
656 struct netfs_root_capabilities
*cap
;
657 struct pohmelfs_sb
*psb
= st
->psb
;
659 if (cmd
->size
!= sizeof(struct netfs_root_capabilities
)) {
667 netfs_convert_root_capabilities(cap
);
669 if (psb
->total_size
< cap
->used
+ cap
->avail
)
670 psb
->total_size
= cap
->used
+ cap
->avail
;
672 psb
->avail_size
= cap
->avail
;
673 psb
->state_flags
= cap
->flags
;
675 if (psb
->state_flags
& POHMELFS_FLAGS_RO
) {
676 psb
->sb
->s_flags
|= MS_RDONLY
;
677 printk(KERN_INFO
"Mounting POHMELFS (%d) read-only.\n", psb
->idx
);
680 if (psb
->state_flags
& POHMELFS_FLAGS_XATTR
)
681 printk(KERN_INFO
"Mounting POHMELFS (%d) "
682 "with extended attributes support.\n", psb
->idx
);
684 if (atomic_long_read(&psb
->total_inodes
) <= 1)
685 atomic_long_set(&psb
->total_inodes
, cap
->nr_files
);
687 dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n",
688 __func__
, psb
->total_size
, psb
->avail_size
, psb
->state_flags
, cap
->nr_files
);
696 * Crypto capabilities of the server, where it says that
697 * it supports or does not requested hash/cipher algorithms.
699 static int pohmelfs_crypto_cap_response(struct netfs_state
*st
)
701 struct netfs_cmd
*cmd
= &st
->cmd
;
702 struct netfs_crypto_capabilities
*cap
;
703 struct pohmelfs_sb
*psb
= st
->psb
;
706 if (cmd
->size
!= sizeof(struct netfs_crypto_capabilities
)) {
714 dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n",
716 psb
->cipher_string
, (cap
->cipher_strlen
) ? "SUPPORTED" : "NOT SUPPORTED",
717 psb
->hash_string
, (cap
->hash_strlen
) ? "SUPPORTED" : "NOT SUPPORTED");
719 if (!cap
->hash_strlen
) {
720 if (psb
->hash_strlen
&& psb
->crypto_fail_unsupported
)
722 psb
->hash_strlen
= 0;
723 kfree(psb
->hash_string
);
724 psb
->hash_string
= NULL
;
727 if (!cap
->cipher_strlen
) {
728 if (psb
->cipher_strlen
&& psb
->crypto_fail_unsupported
)
730 psb
->cipher_strlen
= 0;
731 kfree(psb
->cipher_string
);
732 psb
->cipher_string
= NULL
;
739 * Capabilities handshake response.
741 static int pohmelfs_capabilities_response(struct netfs_state
*st
)
743 struct netfs_cmd
*cmd
= &st
->cmd
;
746 err
= pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
751 case POHMELFS_CRYPTO_CAPABILITIES
:
752 return pohmelfs_crypto_cap_response(st
);
753 case POHMELFS_ROOT_CAPABILITIES
:
754 return pohmelfs_root_cap_response(st
);
762 * Receiving extended attribute.
763 * Does not work properly if received size is more than requested one,
764 * it should not happen with current request/reply model though.
766 static int pohmelfs_getxattr_response(struct netfs_state
*st
)
768 struct pohmelfs_sb
*psb
= st
->psb
;
769 struct netfs_cmd
*cmd
= &st
->cmd
;
770 struct pohmelfs_mcache
*m
;
771 short error
= (signed short)cmd
->ext
, err
;
772 unsigned int sz
, total_size
;
774 m
= pohmelfs_mcache_search(psb
, cmd
->id
);
776 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
777 __func__
, cmd
->id
, (m
) ? m
->gen
: 0, error
);
780 printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__
, cmd
->id
);
785 sz
= min_t(unsigned int, cmd
->size
, m
->size
);
786 err
= pohmelfs_data_recv_and_check(st
, m
->data
, sz
);
793 total_size
= cmd
->size
- sz
;
796 sz
= min(total_size
, st
->size
);
798 err
= pohmelfs_data_recv_and_check(st
, st
->data
, sz
);
810 complete(&m
->complete
);
811 pohmelfs_mcache_put(psb
, m
);
816 int pohmelfs_data_lock_response(struct netfs_state
*st
)
818 struct pohmelfs_sb
*psb
= st
->psb
;
819 struct netfs_cmd
*cmd
= &st
->cmd
;
820 struct pohmelfs_mcache
*m
;
821 short err
= (signed short)cmd
->ext
;
824 m
= pohmelfs_mcache_search(psb
, id
);
826 dprintk("%s: id: %llu, gen: %llu, err: %d.\n",
827 __func__
, cmd
->id
, (m
) ? m
->gen
: 0, err
);
830 pohmelfs_data_recv(st
, st
->data
, cmd
->size
);
831 printk("%s: failed to find data lock response: id: %llu.\n", __func__
, cmd
->id
);
836 err
= pohmelfs_data_recv_and_check(st
, &m
->info
, cmd
->size
);
839 complete(&m
->complete
);
840 pohmelfs_mcache_put(psb
, m
);
845 static void __inline__
netfs_state_reset(struct netfs_state
*st
)
847 netfs_state_lock_send(st
);
848 netfs_state_exit(st
);
849 netfs_state_init(st
);
850 netfs_state_unlock_send(st
);
854 * Main receiving function, called from dedicated kernel thread.
856 static int pohmelfs_recv(void *data
)
859 struct netfs_state
*st
= data
;
860 struct netfs_cmd
*cmd
= &st
->cmd
;
862 while (!kthread_should_stop()) {
864 * If socket will be reset after this statement, then
865 * pohmelfs_data_recv() will just fail and loop will
866 * start again, so it can be done without any locks.
868 * st->read_socket is needed to prevents state machine
869 * breaking between this data reading and subsequent one
870 * in protocol specific functions during connection reset.
871 * In case of reset we have to read next command and do
872 * not expect data for old command to magically appear in
875 st
->read_socket
= st
->socket
;
876 err
= pohmelfs_data_recv(st
, cmd
, sizeof(struct netfs_cmd
));
882 netfs_convert_cmd(cmd
);
884 dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, "
885 "ext: %u, csize: %u, cpad: %u.\n",
886 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
,
887 cmd
->size
, cmd
->ext
, cmd
->csize
, cmd
->cpad
);
890 struct pohmelfs_crypto_engine
*e
= &st
->eng
;
892 if (unlikely(cmd
->csize
> e
->size
/2)) {
893 netfs_state_reset(st
);
897 if (e
->hash
&& unlikely(cmd
->csize
!= st
->psb
->crypto_attached_size
)) {
898 dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, "
899 "csize: %u != digest size %u.\n",
900 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
,
901 cmd
->csize
, st
->psb
->crypto_attached_size
);
902 netfs_state_reset(st
);
906 err
= pohmelfs_data_recv(st
, e
->data
, cmd
->csize
);
908 netfs_state_reset(st
);
912 #ifdef CONFIG_POHMELFS_DEBUG
915 unsigned char *hash
= e
->data
;
917 dprintk("%s: received hash: ", __func__
);
918 for (i
= 0; i
< cmd
->csize
; ++i
)
919 printk("%02x ", hash
[i
]);
924 cmd
->size
-= cmd
->csize
;
928 * This should catch protocol breakage and random garbage instead of commands.
930 if (unlikely((cmd
->size
> st
->size
) && (cmd
->cmd
!= NETFS_XATTR_GET
))) {
931 netfs_state_reset(st
);
936 case NETFS_READ_PAGE
:
937 err
= pohmelfs_read_page_response(st
);
940 err
= pohmelfs_readdir_response(st
);
943 err
= pohmelfs_lookup_response(st
);
946 err
= pohmelfs_create_response(st
);
949 err
= pohmelfs_remove_response(st
);
952 err
= pohmelfs_transaction_response(st
);
954 case NETFS_PAGE_CACHE
:
955 err
= pohmelfs_page_cache_response(st
);
957 case NETFS_CAPABILITIES
:
958 err
= pohmelfs_capabilities_response(st
);
961 err
= pohmelfs_data_lock_response(st
);
963 case NETFS_XATTR_GET
:
964 err
= pohmelfs_getxattr_response(st
);
967 printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n",
968 __func__
, cmd
->cmd
, cmd
->id
, cmd
->start
, cmd
->size
, cmd
->ext
);
969 netfs_state_reset(st
);
974 while (!kthread_should_stop())
975 schedule_timeout_uninterruptible(msecs_to_jiffies(10));
980 int netfs_state_init(struct netfs_state
*st
)
983 struct pohmelfs_ctl
*ctl
= &st
->ctl
;
985 err
= sock_create(ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, &st
->socket
);
987 printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n",
988 __func__
, ctl
->addr
.sa_family
, ctl
->type
, ctl
->proto
, err
);
992 st
->socket
->sk
->sk_allocation
= GFP_NOIO
;
993 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
995 err
= kernel_connect(st
->socket
, (struct sockaddr
*)&ctl
->addr
, ctl
->addrlen
, 0);
997 printk("%s: failed to connect to server: idx: %u, err: %d.\n",
998 __func__
, st
->psb
->idx
, err
);
999 goto err_out_release
;
1001 st
->socket
->sk
->sk_sndtimeo
= st
->socket
->sk
->sk_rcvtimeo
= msecs_to_jiffies(60000);
1003 err
= netfs_poll_init(st
);
1005 goto err_out_release
;
1007 if (st
->socket
->ops
->family
== AF_INET
) {
1008 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ctl
->addr
;
1009 printk(KERN_INFO
"%s: (re)connected to peer %pi4:%d.\n", __func__
,
1010 &sin
->sin_addr
.s_addr
, ntohs(sin
->sin_port
));
1011 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1012 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&ctl
->addr
;
1013 printk(KERN_INFO
"%s: (re)connected to peer %pi6:%d", __func__
,
1014 &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1020 sock_release(st
->socket
);
1026 void netfs_state_exit(struct netfs_state
*st
)
1029 netfs_poll_exit(st
);
1030 st
->socket
->ops
->shutdown(st
->socket
, 2);
1032 if (st
->socket
->ops
->family
== AF_INET
) {
1033 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&st
->ctl
.addr
;
1034 printk(KERN_INFO
"%s: disconnected from peer %pi4:%d.\n", __func__
,
1035 &sin
->sin_addr
.s_addr
, ntohs(sin
->sin_port
));
1036 } else if (st
->socket
->ops
->family
== AF_INET6
) {
1037 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)&st
->ctl
.addr
;
1038 printk(KERN_INFO
"%s: disconnected from peer %pi6:%d", __func__
,
1039 &sin
->sin6_addr
, ntohs(sin
->sin6_port
));
1042 sock_release(st
->socket
);
1044 st
->read_socket
= NULL
;
1049 int pohmelfs_state_init_one(struct pohmelfs_sb
*psb
, struct pohmelfs_config
*conf
)
1051 struct netfs_state
*st
= &conf
->state
;
1054 mutex_init(&st
->__state_lock
);
1055 mutex_init(&st
->__state_send_lock
);
1056 init_waitqueue_head(&st
->thread_wait
);
1059 st
->trans_root
= RB_ROOT
;
1060 mutex_init(&st
->trans_lock
);
1062 st
->size
= psb
->trans_data_size
;
1063 st
->data
= kmalloc(st
->size
, GFP_KERNEL
);
1067 if (psb
->perform_crypto
) {
1068 err
= pohmelfs_crypto_engine_init(&st
->eng
, psb
);
1070 goto err_out_free_data
;
1073 err
= netfs_state_init(st
);
1075 goto err_out_free_engine
;
1077 st
->thread
= kthread_run(pohmelfs_recv
, st
, "pohmelfs/%u", psb
->idx
);
1078 if (IS_ERR(st
->thread
)) {
1079 err
= PTR_ERR(st
->thread
);
1080 goto err_out_netfs_exit
;
1083 if (!psb
->active_state
)
1084 psb
->active_state
= conf
;
1086 dprintk("%s: conf: %p, st: %p, socket: %p.\n",
1087 __func__
, conf
, st
, st
->socket
);
1091 netfs_state_exit(st
);
1092 err_out_free_engine
:
1093 pohmelfs_crypto_engine_exit(&st
->eng
);
1101 void pohmelfs_state_flush_transactions(struct netfs_state
*st
)
1103 struct rb_node
*rb_node
;
1104 struct netfs_trans_dst
*dst
;
1106 mutex_lock(&st
->trans_lock
);
1107 for (rb_node
= rb_first(&st
->trans_root
); rb_node
; ) {
1108 dst
= rb_entry(rb_node
, struct netfs_trans_dst
, state_entry
);
1109 rb_node
= rb_next(rb_node
);
1111 dst
->trans
->result
= -EINVAL
;
1112 netfs_trans_remove_nolock(dst
, st
);
1113 netfs_trans_drop_dst_nostate(dst
);
1115 mutex_unlock(&st
->trans_lock
);
1118 static void pohmelfs_state_exit_one(struct pohmelfs_config
*c
)
1120 struct netfs_state
*st
= &c
->state
;
1122 dprintk("%s: exiting, st: %p.\n", __func__
, st
);
1124 kthread_stop(st
->thread
);
1128 netfs_state_lock_send(st
);
1129 netfs_state_exit(st
);
1130 netfs_state_unlock_send(st
);
1132 pohmelfs_state_flush_transactions(st
);
1134 pohmelfs_crypto_engine_exit(&st
->eng
);
1141 * Initialize network stack. It searches for given ID in global
1142 * configuration table, this contains information of the remote server
1143 * (address (any supported by socket interface) and port, protocol and so on).
1145 int pohmelfs_state_init(struct pohmelfs_sb
*psb
)
1149 err
= pohmelfs_copy_config(psb
);
1151 pohmelfs_state_exit(psb
);
1158 void pohmelfs_state_exit(struct pohmelfs_sb
*psb
)
1160 struct pohmelfs_config
*c
, *tmp
;
1162 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1163 list_del(&c
->config_entry
);
1164 pohmelfs_state_exit_one(c
);
1168 void pohmelfs_switch_active(struct pohmelfs_sb
*psb
)
1170 struct pohmelfs_config
*c
= psb
->active_state
;
1172 if (!list_empty(&psb
->state_list
)) {
1173 if (c
->config_entry
.next
!= &psb
->state_list
) {
1174 psb
->active_state
= list_entry(c
->config_entry
.next
,
1175 struct pohmelfs_config
, config_entry
);
1177 psb
->active_state
= list_entry(psb
->state_list
.next
,
1178 struct pohmelfs_config
, config_entry
);
1181 dprintk("%s: empty: %d, active %p -> %p.\n",
1182 __func__
, list_empty(&psb
->state_list
), c
,
1185 psb
->active_state
= NULL
;
1188 void pohmelfs_check_states(struct pohmelfs_sb
*psb
)
1190 struct pohmelfs_config
*c
, *tmp
;
1191 LIST_HEAD(delete_list
);
1193 mutex_lock(&psb
->state_lock
);
1194 list_for_each_entry_safe(c
, tmp
, &psb
->state_list
, config_entry
) {
1195 if (pohmelfs_config_check(c
, psb
->idx
)) {
1197 if (psb
->active_state
== c
)
1198 pohmelfs_switch_active(psb
);
1199 list_move(&c
->config_entry
, &delete_list
);
1202 pohmelfs_copy_config(psb
);
1203 mutex_unlock(&psb
->state_lock
);
1205 list_for_each_entry_safe(c
, tmp
, &delete_list
, config_entry
) {
1206 list_del(&c
->config_entry
);
1207 pohmelfs_state_exit_one(c
);