at v3.2 1209 lines 30 kB view raw
1/* 2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 * All rights reserved. 4 * 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. 9 * 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. 14 */ 15 16#include <linux/fsnotify.h> 17#include <linux/jhash.h> 18#include <linux/in.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> 27 28#include "netfs.h" 29 30/* 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. 36 * 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. 40 * 41 * If object is not found for given data, it is discarded. 42 * 43 * All requests are received by dedicated kernel thread. 44 */ 45 46/* 47 * Basic network sending/receiving functions. 48 * Blocked mode is used. 49 */ 50static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size) 51{ 52 struct msghdr msg; 53 struct kvec iov; 54 int err; 55 56 BUG_ON(!size); 57 58 iov.iov_base = buf; 59 iov.iov_len = size; 60 61 msg.msg_iov = (struct iovec *)&iov; 62 msg.msg_iovlen = 1; 63 msg.msg_name = NULL; 64 msg.msg_namelen = 0; 65 msg.msg_control = NULL; 66 msg.msg_controllen = 0; 67 msg.msg_flags = MSG_DONTWAIT; 68 69 err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, 70 msg.msg_flags); 71 if (err <= 0) { 72 printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err); 73 if (err == 0) 74 err = -ECONNRESET; 75 } 76 77 return err; 78} 79 80static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size) 81{ 82 unsigned int revents = 0; 83 unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; 84 unsigned int mask = err_mask | POLLIN; 85 int err = 0; 86 87 while (size && !err) { 88 revents = netfs_state_poll(st); 89 90 if (!(revents & mask)) { 91 DEFINE_WAIT(wait); 92 93 for (;;) { 94 prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE); 95 if (kthread_should_stop()) 96 break; 97 98 revents = netfs_state_poll(st); 99 100 if (revents & mask) 101 break; 102 103 if (signal_pending(current)) 104 break; 105 106 schedule(); 107 continue; 108 } 109 finish_wait(&st->thread_wait, &wait); 110 } 111 112 err = 0; 113 netfs_state_lock(st); 114 if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) { 115 err = netfs_data_recv(st, data, size); 116 if (err > 0) { 117 data += err; 118 size -= err; 119 err = 0; 120 } else if (err == 0) 121 err = -ECONNRESET; 122 } 123 124 if (revents & err_mask) { 125 printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", 126 __func__, revents, st->socket, size, err); 127 err = -ECONNRESET; 128 } 129 netfs_state_unlock(st); 130 131 if (err < 0) { 132 if (netfs_state_trylock_send(st)) { 133 netfs_state_exit(st); 134 err = netfs_state_init(st); 135 if (!err) 136 err = -EAGAIN; 137 netfs_state_unlock_send(st); 138 } else { 139 st->need_reset = 1; 140 } 141 } 142 143 if (kthread_should_stop()) 144 err = -ENODEV; 145 146 if (err) 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); 151 } 152 153 return err; 154} 155 156int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size) 157{ 158 struct netfs_cmd *cmd = &st->cmd; 159 int err; 160 161 err = pohmelfs_data_recv(st, data, size); 162 if (err) 163 return err; 164 165 return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size); 166} 167 168/* 169 * Polling machinery. 170 */ 171 172struct netfs_poll_helper { 173 poll_table pt; 174 struct netfs_state *st; 175}; 176 177static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key) 178{ 179 struct netfs_state *st = container_of(wait, struct netfs_state, wait); 180 181 wake_up(&st->thread_wait); 182 return 1; 183} 184 185static void netfs_queue_func(struct file *file, wait_queue_head_t *whead, 186 poll_table *pt) 187{ 188 struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st; 189 190 st->whead = whead; 191 init_waitqueue_func_entry(&st->wait, netfs_queue_wake); 192 add_wait_queue(whead, &st->wait); 193} 194 195static void netfs_poll_exit(struct netfs_state *st) 196{ 197 if (st->whead) { 198 remove_wait_queue(st->whead, &st->wait); 199 st->whead = NULL; 200 } 201} 202 203static int netfs_poll_init(struct netfs_state *st) 204{ 205 struct netfs_poll_helper ph; 206 207 ph.st = st; 208 init_poll_funcptr(&ph.pt, &netfs_queue_func); 209 210 st->socket->ops->poll(NULL, st->socket, &ph.pt); 211 return 0; 212} 213 214/* 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. 218 * 219 * There is a work in progress of allowing to call copy_to_user() directly from 220 * async receiving kernel thread. 221 */ 222static int pohmelfs_read_page_response(struct netfs_state *st) 223{ 224 struct pohmelfs_sb *psb = st->psb; 225 struct netfs_cmd *cmd = &st->cmd; 226 struct inode *inode; 227 struct page *page; 228 int err = 0; 229 230 if (cmd->size > PAGE_CACHE_SIZE) { 231 err = -EINVAL; 232 goto err_out_exit; 233 } 234 235 inode = ilookup(st->psb->sb, cmd->id); 236 if (!inode) { 237 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); 238 err = -ENOENT; 239 goto err_out_exit; 240 } 241 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); 246 247 while (cmd->size) { 248 unsigned int sz = min(cmd->size, st->size); 249 250 err = pohmelfs_data_recv(st, st->data, sz); 251 if (err) 252 break; 253 254 cmd->size -= sz; 255 } 256 257 err = -ENODEV; 258 if (page) 259 goto err_out_page_put; 260 goto err_out_put; 261 } 262 263 if (cmd->size) { 264 void *addr; 265 266 addr = kmap(page); 267 err = pohmelfs_data_recv(st, addr, cmd->size); 268 kunmap(page); 269 270 if (err) 271 goto err_out_page_unlock; 272 } 273 274 dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n", 275 __func__, page, cmd->start, cmd->size, PageLocked(page)); 276 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); 280 if (err < 0) 281 goto err_out_page_unlock; 282 } else { 283 SetPageUptodate(page); 284 unlock_page(page); 285 page_cache_release(page); 286 } 287 288 pohmelfs_put_inode(POHMELFS_I(inode)); 289 wake_up(&st->psb->wait); 290 291 return 0; 292 293err_out_page_unlock: 294 SetPageError(page); 295 unlock_page(page); 296err_out_page_put: 297 page_cache_release(page); 298err_out_put: 299 pohmelfs_put_inode(POHMELFS_I(inode)); 300err_out_exit: 301 wake_up(&st->psb->wait); 302 return err; 303} 304 305static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str, 306 struct netfs_inode_info *info) 307{ 308 struct inode *inode; 309 struct pohmelfs_name *n; 310 int err = 0; 311 u64 ino = 0; 312 313 mutex_lock(&parent->offset_lock); 314 n = pohmelfs_search_hash(parent, str->hash); 315 if (n) 316 ino = n->ino; 317 mutex_unlock(&parent->offset_lock); 318 319 if (!ino) 320 goto out; 321 322 inode = ilookup(parent->vfs_inode.i_sb, ino); 323 if (!inode) 324 goto out; 325 326 dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino); 327 328 pohmelfs_fill_inode(inode, info); 329 pohmelfs_put_inode(POHMELFS_I(inode)); 330 err = -EEXIST; 331out: 332 return err; 333} 334 335/* 336 * Readdir response from server. If special field is set, we wakeup 337 * listener (readdir() call), which will copy data to userspace. 338 */ 339static int pohmelfs_readdir_response(struct netfs_state *st) 340{ 341 struct inode *inode; 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; 346 struct qstr str; 347 348 if (cmd->size > st->size) 349 return -EINVAL; 350 351 inode = ilookup(st->psb->sb, cmd->id); 352 if (!inode) { 353 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); 354 return -ENOENT; 355 } 356 parent = POHMELFS_I(inode); 357 358 if (!cmd->size && cmd->start) { 359 err = -cmd->start; 360 goto out; 361 } 362 363 if (cmd->size) { 364 char *name; 365 366 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); 367 if (err) 368 goto err_out_put; 369 370 info = (struct netfs_inode_info *)(st->data); 371 372 name = (char *)(info + 1); 373 str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; 374 name[str.len] = 0; 375 str.name = name; 376 str.hash = jhash(str.name, str.len, 0); 377 378 netfs_convert_inode_info(info); 379 380 if (parent) { 381 err = pohmelfs_check_name(parent, &str, info); 382 if (err) { 383 if (err == -EEXIST) 384 err = 0; 385 goto out; 386 } 387 } 388 389 info->ino = cmd->start; 390 if (!info->ino) 391 info->ino = pohmelfs_new_ino(st->psb); 392 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, 395 info->mode); 396 397 npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); 398 if (IS_ERR(npi)) { 399 err = PTR_ERR(npi); 400 401 if (err != -EEXIST) 402 goto err_out_put; 403 } else { 404 struct dentry *dentry, *alias, *pd; 405 406 set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); 407 clear_bit(NETFS_INODE_OWNED, &npi->state); 408 409 pd = d_find_alias(&parent->vfs_inode); 410 if (pd) { 411 str.hash = full_name_hash(str.name, str.len); 412 dentry = d_alloc(pd, &str); 413 if (dentry) { 414 alias = d_materialise_unique(dentry, &npi->vfs_inode); 415 if (alias) 416 dput(alias); 417 } 418 419 dput(dentry); 420 dput(pd); 421 } 422 } 423 } 424out: 425 if (last) { 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); 429 } 430 pohmelfs_put_inode(parent); 431 432 return err; 433 434err_out_put: 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); 439 return err; 440} 441 442/* 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. 447 */ 448static int pohmelfs_lookup_response(struct netfs_state *st) 449{ 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; 454 int err = -EINVAL; 455 char *name; 456 457 inode = ilookup(st->psb->sb, cmd->id); 458 if (!inode) { 459 printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n", 460 __func__, cmd->id, cmd->start, cmd->size); 461 err = -ENOENT; 462 goto err_out_exit; 463 } 464 parent = POHMELFS_I(inode); 465 466 if (!cmd->size) { 467 err = -cmd->start; 468 goto err_out_put; 469 } 470 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); 474 err = -EINVAL; 475 goto err_out_put; 476 } 477 478 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); 479 if (err) 480 goto err_out_put; 481 482 info = (struct netfs_inode_info *)(st->data); 483 name = (char *)(info + 1); 484 485 netfs_convert_inode_info(info); 486 487 info->ino = cmd->start; 488 if (!info->ino) 489 info->ino = pohmelfs_new_ino(st->psb); 490 491 dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n", 492 __func__, parent->ino, info->ino, name, cmd->start); 493 494 if (cmd->start) 495 npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0); 496 else { 497 struct qstr str; 498 499 str.name = name; 500 str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; 501 str.hash = jhash(name, str.len, 0); 502 503 npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); 504 } 505 if (IS_ERR(npi)) { 506 err = PTR_ERR(npi); 507 508 if (err != -EEXIST) 509 goto err_out_put; 510 } else { 511 set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); 512 clear_bit(NETFS_INODE_OWNED, &npi->state); 513 } 514 515 clear_bit(NETFS_COMMAND_PENDING, &parent->state); 516 pohmelfs_put_inode(parent); 517 518 wake_up(&st->psb->wait); 519 520 return 0; 521 522err_out_put: 523 pohmelfs_put_inode(parent); 524err_out_exit: 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); 529 return err; 530} 531 532/* 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. 535 */ 536static int pohmelfs_create_response(struct netfs_state *st) 537{ 538 struct inode *inode; 539 struct netfs_cmd *cmd = &st->cmd; 540 struct pohmelfs_inode *pi; 541 542 inode = ilookup(st->psb->sb, cmd->id); 543 if (!inode) { 544 printk("%s: failed to find inode: id: %llu, start: %llu.\n", 545 __func__, cmd->id, cmd->start); 546 goto err_out_exit; 547 } 548 549 pi = POHMELFS_I(inode); 550 551 /* 552 * To lock or not to lock? 553 * We actually do not care if it races... 554 */ 555 if (cmd->start) 556 make_bad_inode(inode); 557 set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); 558 559 pohmelfs_put_inode(pi); 560 561 wake_up(&st->psb->wait); 562 return 0; 563 564err_out_exit: 565 wake_up(&st->psb->wait); 566 return -ENOENT; 567} 568 569/* 570 * Object remove response. Just says that remove request has been received. 571 * Used in cache coherency protocol. 572 */ 573static int pohmelfs_remove_response(struct netfs_state *st) 574{ 575 struct netfs_cmd *cmd = &st->cmd; 576 int err; 577 578 err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); 579 if (err) 580 return err; 581 582 dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data); 583 584 return 0; 585} 586 587/* 588 * Transaction reply processing. 589 * 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. 595 */ 596static int pohmelfs_transaction_response(struct netfs_state *st) 597{ 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; 602 603 mutex_lock(&st->trans_lock); 604 dst = netfs_trans_search(st, cmd->start); 605 if (dst) { 606 netfs_trans_remove_nolock(dst, st); 607 t = dst->trans; 608 } 609 mutex_unlock(&st->trans_lock); 610 611 if (!t) { 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); 614 err = -EINVAL; 615 goto out; 616 } 617 618 t->result = err; 619 netfs_trans_drop_dst_nostate(dst); 620 621out: 622 wake_up(&st->psb->wait); 623 return err; 624} 625 626/* 627 * Inode metadata cache coherency message. 628 */ 629static int pohmelfs_page_cache_response(struct netfs_state *st) 630{ 631 struct netfs_cmd *cmd = &st->cmd; 632 struct inode *inode; 633 634 dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size); 635 636 inode = ilookup(st->psb->sb, cmd->id); 637 if (!inode) { 638 printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); 639 return -ENOENT; 640 } 641 642 set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state); 643 pohmelfs_put_inode(POHMELFS_I(inode)); 644 645 return 0; 646} 647 648/* 649 * Root capabilities response: export statistics 650 * like used and available size, number of files and dirs, 651 * permissions. 652 */ 653static int pohmelfs_root_cap_response(struct netfs_state *st) 654{ 655 struct netfs_cmd *cmd = &st->cmd; 656 struct netfs_root_capabilities *cap; 657 struct pohmelfs_sb *psb = st->psb; 658 659 if (cmd->size != sizeof(struct netfs_root_capabilities)) { 660 psb->flags = EPROTO; 661 wake_up(&psb->wait); 662 return -EPROTO; 663 } 664 665 cap = st->data; 666 667 netfs_convert_root_capabilities(cap); 668 669 if (psb->total_size < cap->used + cap->avail) 670 psb->total_size = cap->used + cap->avail; 671 if (cap->avail) 672 psb->avail_size = cap->avail; 673 psb->state_flags = cap->flags; 674 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); 678 } 679 680 if (psb->state_flags & POHMELFS_FLAGS_XATTR) 681 printk(KERN_INFO "Mounting POHMELFS (%d) " 682 "with extended attributes support.\n", psb->idx); 683 684 if (atomic_long_read(&psb->total_inodes) <= 1) 685 atomic_long_set(&psb->total_inodes, cap->nr_files); 686 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); 689 690 psb->flags = 0; 691 wake_up(&psb->wait); 692 return 0; 693} 694 695/* 696 * Crypto capabilities of the server, where it says that 697 * it supports or does not requested hash/cipher algorithms. 698 */ 699static int pohmelfs_crypto_cap_response(struct netfs_state *st) 700{ 701 struct netfs_cmd *cmd = &st->cmd; 702 struct netfs_crypto_capabilities *cap; 703 struct pohmelfs_sb *psb = st->psb; 704 int err = 0; 705 706 if (cmd->size != sizeof(struct netfs_crypto_capabilities)) { 707 psb->flags = EPROTO; 708 wake_up(&psb->wait); 709 return -EPROTO; 710 } 711 712 cap = st->data; 713 714 dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n", 715 __func__, 716 psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED", 717 psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED"); 718 719 if (!cap->hash_strlen) { 720 if (psb->hash_strlen && psb->crypto_fail_unsupported) 721 err = -ENOTSUPP; 722 psb->hash_strlen = 0; 723 kfree(psb->hash_string); 724 psb->hash_string = NULL; 725 } 726 727 if (!cap->cipher_strlen) { 728 if (psb->cipher_strlen && psb->crypto_fail_unsupported) 729 err = -ENOTSUPP; 730 psb->cipher_strlen = 0; 731 kfree(psb->cipher_string); 732 psb->cipher_string = NULL; 733 } 734 735 return err; 736} 737 738/* 739 * Capabilities handshake response. 740 */ 741static int pohmelfs_capabilities_response(struct netfs_state *st) 742{ 743 struct netfs_cmd *cmd = &st->cmd; 744 int err = 0; 745 746 err = pohmelfs_data_recv(st, st->data, cmd->size); 747 if (err) 748 return err; 749 750 switch (cmd->id) { 751 case POHMELFS_CRYPTO_CAPABILITIES: 752 return pohmelfs_crypto_cap_response(st); 753 case POHMELFS_ROOT_CAPABILITIES: 754 return pohmelfs_root_cap_response(st); 755 default: 756 break; 757 } 758 return -EINVAL; 759} 760 761/* 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. 765 */ 766static int pohmelfs_getxattr_response(struct netfs_state *st) 767{ 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; 773 774 m = pohmelfs_mcache_search(psb, cmd->id); 775 776 dprintk("%s: id: %llu, gen: %llu, err: %d.\n", 777 __func__, cmd->id, (m) ? m->gen : 0, error); 778 779 if (!m) { 780 printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id); 781 return -ENOENT; 782 } 783 784 if (cmd->size) { 785 sz = min_t(unsigned int, cmd->size, m->size); 786 err = pohmelfs_data_recv_and_check(st, m->data, sz); 787 if (err) { 788 error = err; 789 goto out; 790 } 791 792 m->size = sz; 793 total_size = cmd->size - sz; 794 795 while (total_size) { 796 sz = min(total_size, st->size); 797 798 err = pohmelfs_data_recv_and_check(st, st->data, sz); 799 if (err) { 800 error = err; 801 break; 802 } 803 804 total_size -= sz; 805 } 806 } 807 808out: 809 m->err = error; 810 complete(&m->complete); 811 pohmelfs_mcache_put(psb, m); 812 813 return error; 814} 815 816int pohmelfs_data_lock_response(struct netfs_state *st) 817{ 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; 822 u64 id = cmd->id; 823 824 m = pohmelfs_mcache_search(psb, id); 825 826 dprintk("%s: id: %llu, gen: %llu, err: %d.\n", 827 __func__, cmd->id, (m) ? m->gen : 0, err); 828 829 if (!m) { 830 pohmelfs_data_recv(st, st->data, cmd->size); 831 printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id); 832 return -ENOENT; 833 } 834 835 if (cmd->size) 836 err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size); 837 838 m->err = err; 839 complete(&m->complete); 840 pohmelfs_mcache_put(psb, m); 841 842 return err; 843} 844 845static void __inline__ netfs_state_reset(struct netfs_state *st) 846{ 847 netfs_state_lock_send(st); 848 netfs_state_exit(st); 849 netfs_state_init(st); 850 netfs_state_unlock_send(st); 851} 852 853/* 854 * Main receiving function, called from dedicated kernel thread. 855 */ 856static int pohmelfs_recv(void *data) 857{ 858 int err = -EINTR; 859 struct netfs_state *st = data; 860 struct netfs_cmd *cmd = &st->cmd; 861 862 while (!kthread_should_stop()) { 863 /* 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. 867 * 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 873 * new connection. 874 */ 875 st->read_socket = st->socket; 876 err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd)); 877 if (err) { 878 msleep(1000); 879 continue; 880 } 881 882 netfs_convert_cmd(cmd); 883 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); 888 889 if (cmd->csize) { 890 struct pohmelfs_crypto_engine *e = &st->eng; 891 892 if (unlikely(cmd->csize > e->size/2)) { 893 netfs_state_reset(st); 894 continue; 895 } 896 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); 903 continue; 904 } 905 906 err = pohmelfs_data_recv(st, e->data, cmd->csize); 907 if (err) { 908 netfs_state_reset(st); 909 continue; 910 } 911 912#ifdef CONFIG_POHMELFS_DEBUG 913 { 914 unsigned int i; 915 unsigned char *hash = e->data; 916 917 dprintk("%s: received hash: ", __func__); 918 for (i = 0; i < cmd->csize; ++i) 919 printk("%02x ", hash[i]); 920 921 printk("\n"); 922 } 923#endif 924 cmd->size -= cmd->csize; 925 } 926 927 /* 928 * This should catch protocol breakage and random garbage instead of commands. 929 */ 930 if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) { 931 netfs_state_reset(st); 932 continue; 933 } 934 935 switch (cmd->cmd) { 936 case NETFS_READ_PAGE: 937 err = pohmelfs_read_page_response(st); 938 break; 939 case NETFS_READDIR: 940 err = pohmelfs_readdir_response(st); 941 break; 942 case NETFS_LOOKUP: 943 err = pohmelfs_lookup_response(st); 944 break; 945 case NETFS_CREATE: 946 err = pohmelfs_create_response(st); 947 break; 948 case NETFS_REMOVE: 949 err = pohmelfs_remove_response(st); 950 break; 951 case NETFS_TRANS: 952 err = pohmelfs_transaction_response(st); 953 break; 954 case NETFS_PAGE_CACHE: 955 err = pohmelfs_page_cache_response(st); 956 break; 957 case NETFS_CAPABILITIES: 958 err = pohmelfs_capabilities_response(st); 959 break; 960 case NETFS_LOCK: 961 err = pohmelfs_data_lock_response(st); 962 break; 963 case NETFS_XATTR_GET: 964 err = pohmelfs_getxattr_response(st); 965 break; 966 default: 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); 970 break; 971 } 972 } 973 974 while (!kthread_should_stop()) 975 schedule_timeout_uninterruptible(msecs_to_jiffies(10)); 976 977 return err; 978} 979 980int netfs_state_init(struct netfs_state *st) 981{ 982 int err; 983 struct pohmelfs_ctl *ctl = &st->ctl; 984 985 err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket); 986 if (err) { 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); 989 goto err_out_exit; 990 } 991 992 st->socket->sk->sk_allocation = GFP_NOIO; 993 st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); 994 995 err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0); 996 if (err) { 997 printk("%s: failed to connect to server: idx: %u, err: %d.\n", 998 __func__, st->psb->idx, err); 999 goto err_out_release; 1000 } 1001 st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); 1002 1003 err = netfs_poll_init(st); 1004 if (err) 1005 goto err_out_release; 1006 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)); 1015 } 1016 1017 return 0; 1018 1019err_out_release: 1020 sock_release(st->socket); 1021err_out_exit: 1022 st->socket = NULL; 1023 return err; 1024} 1025 1026void netfs_state_exit(struct netfs_state *st) 1027{ 1028 if (st->socket) { 1029 netfs_poll_exit(st); 1030 st->socket->ops->shutdown(st->socket, 2); 1031 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)); 1040 } 1041 1042 sock_release(st->socket); 1043 st->socket = NULL; 1044 st->read_socket = NULL; 1045 st->need_reset = 0; 1046 } 1047} 1048 1049int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf) 1050{ 1051 struct netfs_state *st = &conf->state; 1052 int err = -ENOMEM; 1053 1054 mutex_init(&st->__state_lock); 1055 mutex_init(&st->__state_send_lock); 1056 init_waitqueue_head(&st->thread_wait); 1057 1058 st->psb = psb; 1059 st->trans_root = RB_ROOT; 1060 mutex_init(&st->trans_lock); 1061 1062 st->size = psb->trans_data_size; 1063 st->data = kmalloc(st->size, GFP_KERNEL); 1064 if (!st->data) 1065 goto err_out_exit; 1066 1067 if (psb->perform_crypto) { 1068 err = pohmelfs_crypto_engine_init(&st->eng, psb); 1069 if (err) 1070 goto err_out_free_data; 1071 } 1072 1073 err = netfs_state_init(st); 1074 if (err) 1075 goto err_out_free_engine; 1076 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; 1081 } 1082 1083 if (!psb->active_state) 1084 psb->active_state = conf; 1085 1086 dprintk("%s: conf: %p, st: %p, socket: %p.\n", 1087 __func__, conf, st, st->socket); 1088 return 0; 1089 1090err_out_netfs_exit: 1091 netfs_state_exit(st); 1092err_out_free_engine: 1093 pohmelfs_crypto_engine_exit(&st->eng); 1094err_out_free_data: 1095 kfree(st->data); 1096err_out_exit: 1097 return err; 1098 1099} 1100 1101void pohmelfs_state_flush_transactions(struct netfs_state *st) 1102{ 1103 struct rb_node *rb_node; 1104 struct netfs_trans_dst *dst; 1105 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); 1110 1111 dst->trans->result = -EINVAL; 1112 netfs_trans_remove_nolock(dst, st); 1113 netfs_trans_drop_dst_nostate(dst); 1114 } 1115 mutex_unlock(&st->trans_lock); 1116} 1117 1118static void pohmelfs_state_exit_one(struct pohmelfs_config *c) 1119{ 1120 struct netfs_state *st = &c->state; 1121 1122 dprintk("%s: exiting, st: %p.\n", __func__, st); 1123 if (st->thread) { 1124 kthread_stop(st->thread); 1125 st->thread = NULL; 1126 } 1127 1128 netfs_state_lock_send(st); 1129 netfs_state_exit(st); 1130 netfs_state_unlock_send(st); 1131 1132 pohmelfs_state_flush_transactions(st); 1133 1134 pohmelfs_crypto_engine_exit(&st->eng); 1135 kfree(st->data); 1136 1137 kfree(c); 1138} 1139 1140/* 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). 1144 */ 1145int pohmelfs_state_init(struct pohmelfs_sb *psb) 1146{ 1147 int err = -ENOMEM; 1148 1149 err = pohmelfs_copy_config(psb); 1150 if (err) { 1151 pohmelfs_state_exit(psb); 1152 return err; 1153 } 1154 1155 return 0; 1156} 1157 1158void pohmelfs_state_exit(struct pohmelfs_sb *psb) 1159{ 1160 struct pohmelfs_config *c, *tmp; 1161 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); 1165 } 1166} 1167 1168void pohmelfs_switch_active(struct pohmelfs_sb *psb) 1169{ 1170 struct pohmelfs_config *c = psb->active_state; 1171 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); 1176 } else { 1177 psb->active_state = list_entry(psb->state_list.next, 1178 struct pohmelfs_config, config_entry); 1179 } 1180 1181 dprintk("%s: empty: %d, active %p -> %p.\n", 1182 __func__, list_empty(&psb->state_list), c, 1183 psb->active_state); 1184 } else 1185 psb->active_state = NULL; 1186} 1187 1188void pohmelfs_check_states(struct pohmelfs_sb *psb) 1189{ 1190 struct pohmelfs_config *c, *tmp; 1191 LIST_HEAD(delete_list); 1192 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)) { 1196 1197 if (psb->active_state == c) 1198 pohmelfs_switch_active(psb); 1199 list_move(&c->config_entry, &delete_list); 1200 } 1201 } 1202 pohmelfs_copy_config(psb); 1203 mutex_unlock(&psb->state_lock); 1204 1205 list_for_each_entry_safe(c, tmp, &delete_list, config_entry) { 1206 list_del(&c->config_entry); 1207 pohmelfs_state_exit_one(c); 1208 } 1209}