at v3.0 706 lines 17 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/module.h> 17#include <linux/crypto.h> 18#include <linux/fs.h> 19#include <linux/jhash.h> 20#include <linux/hash.h> 21#include <linux/ktime.h> 22#include <linux/mempool.h> 23#include <linux/mm.h> 24#include <linux/mount.h> 25#include <linux/pagemap.h> 26#include <linux/parser.h> 27#include <linux/poll.h> 28#include <linux/swap.h> 29#include <linux/slab.h> 30#include <linux/statfs.h> 31#include <linux/writeback.h> 32 33#include "netfs.h" 34 35static struct kmem_cache *netfs_trans_dst; 36static mempool_t *netfs_trans_dst_pool; 37 38static void netfs_trans_init_static(struct netfs_trans *t, int num, int size) 39{ 40 t->page_num = num; 41 t->total_size = size; 42 atomic_set(&t->refcnt, 1); 43 44 spin_lock_init(&t->dst_lock); 45 INIT_LIST_HEAD(&t->dst_list); 46} 47 48static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st) 49{ 50 int err = 0; 51 unsigned int i, attached_pages = t->attached_pages, ci; 52 struct msghdr msg; 53 struct page **pages = (t->eng)?t->eng->pages:t->pages; 54 struct page *p; 55 unsigned int size; 56 57 msg.msg_name = NULL; 58 msg.msg_namelen = 0; 59 msg.msg_control = NULL; 60 msg.msg_controllen = 0; 61 msg.msg_flags = MSG_WAITALL | MSG_MORE; 62 63 ci = 0; 64 for (i=0; i<t->page_num; ++i) { 65 struct page *page = pages[ci]; 66 struct netfs_cmd cmd; 67 struct iovec io; 68 69 p = t->pages[i]; 70 71 if (!p) 72 continue; 73 74 size = page_private(p); 75 76 io.iov_base = &cmd; 77 io.iov_len = sizeof(struct netfs_cmd); 78 79 cmd.cmd = NETFS_WRITE_PAGE; 80 cmd.ext = 0; 81 cmd.id = 0; 82 cmd.size = size; 83 cmd.start = p->index; 84 cmd.start <<= PAGE_CACHE_SHIFT; 85 cmd.csize = 0; 86 cmd.cpad = 0; 87 cmd.iv = pohmelfs_gen_iv(t); 88 89 netfs_convert_cmd(&cmd); 90 91 msg.msg_iov = &io; 92 msg.msg_iovlen = 1; 93 msg.msg_flags = MSG_WAITALL | MSG_MORE; 94 95 err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd)); 96 if (err <= 0) { 97 printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n", 98 __func__, i, t->page_num, t, t->gen, err); 99 if (err == 0) 100 err = -ECONNRESET; 101 goto err_out; 102 } 103 104 msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 : 105 MSG_MORE); 106 107 err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags); 108 if (err <= 0) { 109 printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n", 110 __func__, i, t->page_num, t, t->gen, size, err); 111 if (err == 0) 112 err = -ECONNRESET; 113 goto err_out; 114 } 115 116 dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n", 117 __func__, i, t->page_num, t, t->gen, page, p, size); 118 119 err = 0; 120 attached_pages--; 121 if (!attached_pages) 122 break; 123 ci++; 124 125 continue; 126 127err_out: 128 printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err); 129 netfs_state_exit(st); 130 break; 131 } 132 133 return err; 134} 135 136int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st) 137{ 138 int err; 139 struct msghdr msg; 140 141 BUG_ON(!t->iovec.iov_len); 142 BUG_ON(t->iovec.iov_len > 1024*1024*1024); 143 144 netfs_state_lock_send(st); 145 if (!st->socket) { 146 err = netfs_state_init(st); 147 if (err) 148 goto err_out_unlock_return; 149 } 150 151 msg.msg_iov = &t->iovec; 152 msg.msg_iovlen = 1; 153 msg.msg_name = NULL; 154 msg.msg_namelen = 0; 155 msg.msg_control = NULL; 156 msg.msg_controllen = 0; 157 msg.msg_flags = MSG_WAITALL; 158 159 if (t->attached_pages) 160 msg.msg_flags |= MSG_MORE; 161 162 err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len); 163 if (err <= 0) { 164 printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n", 165 __func__, t, t->gen, t->iovec.iov_len, err); 166 if (err == 0) 167 err = -ECONNRESET; 168 goto err_out_unlock_return; 169 } 170 171 dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n", 172 __func__, (t->page_num)?"partial":"full", 173 t, t->gen, t->iovec.iov_len, t->page_num); 174 175 err = 0; 176 if (t->attached_pages) 177 err = netfs_trans_send_pages(t, st); 178 179err_out_unlock_return: 180 181 if (st->need_reset) 182 netfs_state_exit(st); 183 184 netfs_state_unlock_send(st); 185 186 dprintk("%s: t: %p, gen: %u, err: %d.\n", 187 __func__, t, t->gen, err); 188 189 t->result = err; 190 return err; 191} 192 193static inline int netfs_trans_cmp(unsigned int gen, unsigned int new) 194{ 195 if (gen < new) 196 return 1; 197 if (gen > new) 198 return -1; 199 return 0; 200} 201 202struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen) 203{ 204 struct rb_root *root = &st->trans_root; 205 struct rb_node *n = root->rb_node; 206 struct netfs_trans_dst *tmp, *ret = NULL; 207 struct netfs_trans *t; 208 int cmp; 209 210 while (n) { 211 tmp = rb_entry(n, struct netfs_trans_dst, state_entry); 212 t = tmp->trans; 213 214 cmp = netfs_trans_cmp(t->gen, gen); 215 if (cmp < 0) 216 n = n->rb_left; 217 else if (cmp > 0) 218 n = n->rb_right; 219 else { 220 ret = tmp; 221 break; 222 } 223 } 224 225 return ret; 226} 227 228static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st) 229{ 230 struct rb_root *root = &st->trans_root; 231 struct rb_node **n = &root->rb_node, *parent = NULL; 232 struct netfs_trans_dst *ret = NULL, *tmp; 233 struct netfs_trans *t = NULL, *new = ndst->trans; 234 int cmp; 235 236 while (*n) { 237 parent = *n; 238 239 tmp = rb_entry(parent, struct netfs_trans_dst, state_entry); 240 t = tmp->trans; 241 242 cmp = netfs_trans_cmp(t->gen, new->gen); 243 if (cmp < 0) 244 n = &parent->rb_left; 245 else if (cmp > 0) 246 n = &parent->rb_right; 247 else { 248 ret = tmp; 249 break; 250 } 251 } 252 253 if (ret) { 254 printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, " 255 "new: gen: %u, flags: %x, send_time: %lu.\n", 256 __func__, t->gen, t->flags, ret->send_time, 257 new->gen, new->flags, ndst->send_time); 258 return -EEXIST; 259 } 260 261 rb_link_node(&ndst->state_entry, parent, n); 262 rb_insert_color(&ndst->state_entry, root); 263 ndst->send_time = jiffies; 264 265 return 0; 266} 267 268int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st) 269{ 270 if (dst && dst->state_entry.rb_parent_color) { 271 rb_erase(&dst->state_entry, &st->trans_root); 272 dst->state_entry.rb_parent_color = 0; 273 return 1; 274 } 275 return 0; 276} 277 278static int netfs_trans_remove_state(struct netfs_trans_dst *dst) 279{ 280 int ret; 281 struct netfs_state *st = dst->state; 282 283 mutex_lock(&st->trans_lock); 284 ret = netfs_trans_remove_nolock(dst, st); 285 mutex_unlock(&st->trans_lock); 286 287 return ret; 288} 289 290/* 291 * Create new destination for given transaction associated with given network state. 292 * Transaction's reference counter is bumped and will be dropped when either 293 * reply is received or when async timeout detection task will fail resending 294 * and drop transaction. 295 */ 296static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st) 297{ 298 struct netfs_trans_dst *dst; 299 int err; 300 301 dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL); 302 if (!dst) 303 return -ENOMEM; 304 305 dst->retries = 0; 306 dst->send_time = 0; 307 dst->state = st; 308 dst->trans = t; 309 netfs_trans_get(t); 310 311 mutex_lock(&st->trans_lock); 312 err = netfs_trans_insert(dst, st); 313 mutex_unlock(&st->trans_lock); 314 315 if (err) 316 goto err_out_free; 317 318 spin_lock(&t->dst_lock); 319 list_add_tail(&dst->trans_entry, &t->dst_list); 320 spin_unlock(&t->dst_lock); 321 322 return 0; 323 324err_out_free: 325 t->result = err; 326 netfs_trans_put(t); 327 mempool_free(dst, netfs_trans_dst_pool); 328 return err; 329} 330 331static void netfs_trans_free_dst(struct netfs_trans_dst *dst) 332{ 333 netfs_trans_put(dst->trans); 334 mempool_free(dst, netfs_trans_dst_pool); 335} 336 337static void netfs_trans_remove_dst(struct netfs_trans_dst *dst) 338{ 339 if (netfs_trans_remove_state(dst)) 340 netfs_trans_free_dst(dst); 341} 342 343/* 344 * Drop destination transaction entry when we know it. 345 */ 346void netfs_trans_drop_dst(struct netfs_trans_dst *dst) 347{ 348 struct netfs_trans *t = dst->trans; 349 350 spin_lock(&t->dst_lock); 351 list_del_init(&dst->trans_entry); 352 spin_unlock(&t->dst_lock); 353 354 netfs_trans_remove_dst(dst); 355} 356 357/* 358 * Drop destination transaction entry when we know it and when we 359 * already removed dst from state tree. 360 */ 361void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst) 362{ 363 struct netfs_trans *t = dst->trans; 364 365 spin_lock(&t->dst_lock); 366 list_del_init(&dst->trans_entry); 367 spin_unlock(&t->dst_lock); 368 369 netfs_trans_free_dst(dst); 370} 371 372/* 373 * This drops destination transaction entry from appropriate network state 374 * tree and drops related reference counter. It is possible that transaction 375 * will be freed here if its reference counter hits zero. 376 * Destination transaction entry will be freed. 377 */ 378void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st) 379{ 380 struct netfs_trans_dst *dst, *tmp, *ret = NULL; 381 382 spin_lock(&t->dst_lock); 383 list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { 384 if (dst->state == st) { 385 ret = dst; 386 list_del(&dst->trans_entry); 387 break; 388 } 389 } 390 spin_unlock(&t->dst_lock); 391 392 if (ret) 393 netfs_trans_remove_dst(ret); 394} 395 396/* 397 * This drops destination transaction entry from appropriate network state 398 * tree and drops related reference counter. It is possible that transaction 399 * will be freed here if its reference counter hits zero. 400 * Destination transaction entry will be freed. 401 */ 402void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st) 403{ 404 struct netfs_trans_dst *dst, *tmp, *ret; 405 406 spin_lock(&t->dst_lock); 407 ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry); 408 if (ret->state != st) { 409 ret = NULL; 410 list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { 411 if (dst->state == st) { 412 ret = dst; 413 list_del_init(&dst->trans_entry); 414 break; 415 } 416 } 417 } else { 418 list_del(&ret->trans_entry); 419 } 420 spin_unlock(&t->dst_lock); 421 422 if (ret) 423 netfs_trans_remove_dst(ret); 424} 425 426static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st) 427{ 428 int err; 429 430 err = netfs_trans_push_dst(t, st); 431 if (err) 432 return err; 433 434 err = netfs_trans_send(t, st); 435 if (err) 436 goto err_out_free; 437 438 if (t->flags & NETFS_TRANS_SINGLE_DST) 439 pohmelfs_switch_active(st->psb); 440 441 return 0; 442 443err_out_free: 444 t->result = err; 445 netfs_trans_drop_last(t, st); 446 447 return err; 448} 449 450int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb) 451{ 452 struct pohmelfs_config *c; 453 int err = -ENODEV; 454 struct netfs_state *st; 455#if 0 456 dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n", 457 __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state); 458#endif 459 mutex_lock(&psb->state_lock); 460 list_for_each_entry(c, &psb->state_list, config_entry) { 461 st = &c->state; 462 463 if (t->flags & NETFS_TRANS_SINGLE_DST) { 464 if (!(st->ctl.perm & POHMELFS_IO_PERM_READ)) 465 continue; 466 } else { 467 if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE)) 468 continue; 469 } 470 471 if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) && 472 (t->flags & NETFS_TRANS_SINGLE_DST)) 473 st = &psb->active_state->state; 474 475 err = netfs_trans_push(t, st); 476 if (!err && (t->flags & NETFS_TRANS_SINGLE_DST)) 477 break; 478 } 479 480 mutex_unlock(&psb->state_lock); 481#if 0 482 dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n", 483 __func__, t, t->gen, t->iovec.iov_len, t->page_num, err); 484#endif 485 if (err) 486 t->result = err; 487 return err; 488} 489 490int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb) 491{ 492 int err; 493 struct netfs_cmd *cmd = t->iovec.iov_base; 494 495 t->gen = atomic_inc_return(&psb->trans_gen); 496 497 cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) + 498 t->attached_size + t->attached_pages * sizeof(struct netfs_cmd); 499 cmd->cmd = NETFS_TRANS; 500 cmd->start = t->gen; 501 cmd->id = 0; 502 503 if (psb->perform_crypto) { 504 cmd->ext = psb->crypto_attached_size; 505 cmd->csize = psb->crypto_attached_size; 506 } 507 508 dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n", 509 __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages); 510 err = pohmelfs_trans_crypt(t, psb); 511 if (err) { 512 t->result = err; 513 netfs_convert_cmd(cmd); 514 dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n", 515 __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err); 516 } 517 netfs_trans_put(t); 518 return err; 519} 520 521/* 522 * Resend transaction to remote server(s). 523 * If new servers were added into superblock, we can try to send data 524 * to them too. 525 * 526 * It is called under superblock's state_lock, so we can safely 527 * dereference psb->state_list. Also, transaction's reference counter is 528 * bumped, so it can not go away under us, thus we can safely access all 529 * its members. State is locked. 530 * 531 * This function returns 0 if transaction was successfully sent to at 532 * least one destination target. 533 */ 534int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb) 535{ 536 struct netfs_trans_dst *dst; 537 struct netfs_state *st; 538 struct pohmelfs_config *c; 539 int err, exist, error = -ENODEV; 540 541 list_for_each_entry(c, &psb->state_list, config_entry) { 542 st = &c->state; 543 544 exist = 0; 545 spin_lock(&t->dst_lock); 546 list_for_each_entry(dst, &t->dst_list, trans_entry) { 547 if (st == dst->state) { 548 exist = 1; 549 break; 550 } 551 } 552 spin_unlock(&t->dst_lock); 553 554 if (exist) { 555 if (!(t->flags & NETFS_TRANS_SINGLE_DST) || 556 (c->config_entry.next == &psb->state_list)) { 557 dprintk("%s: resending st: %p, t: %p, gen: %u.\n", 558 __func__, st, t, t->gen); 559 err = netfs_trans_send(t, st); 560 if (!err) 561 error = 0; 562 } 563 continue; 564 } 565 566 dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n", 567 __func__, st, t, t->gen); 568 err = netfs_trans_push(t, st); 569 if (err) 570 continue; 571 error = 0; 572 if (t->flags & NETFS_TRANS_SINGLE_DST) 573 break; 574 } 575 576 t->result = error; 577 return error; 578} 579 580void *netfs_trans_add(struct netfs_trans *t, unsigned int size) 581{ 582 struct iovec *io = &t->iovec; 583 void *ptr; 584 585 if (size > t->total_size) { 586 ptr = ERR_PTR(-EINVAL); 587 goto out; 588 } 589 590 if (io->iov_len + size > t->total_size) { 591 dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n", 592 __func__, t, t->gen, io->iov_len, size, t->total_size); 593 ptr = ERR_PTR(-E2BIG); 594 goto out; 595 } 596 597 ptr = io->iov_base + io->iov_len; 598 io->iov_len += size; 599 600out: 601 dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n", 602 __func__, t, t->gen, size, io->iov_len); 603 return ptr; 604} 605 606void netfs_trans_free(struct netfs_trans *t) 607{ 608 if (t->eng) 609 pohmelfs_crypto_thread_make_ready(t->eng->thread); 610 kfree(t); 611} 612 613struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size, 614 unsigned int flags, unsigned int nr) 615{ 616 struct netfs_trans *t; 617 unsigned int num, cont, pad, size_no_trans; 618 unsigned int crypto_added = 0; 619 struct netfs_cmd *cmd; 620 621 if (psb->perform_crypto) 622 crypto_added = psb->crypto_attached_size; 623 624 /* 625 * |sizeof(struct netfs_trans)| 626 * |sizeof(struct netfs_cmd)| - transaction header 627 * |size| - buffer with requested size 628 * |padding| - crypto padding, zero bytes 629 * |nr * sizeof(struct page *)| - array of page pointers 630 * 631 * Overall size should be less than PAGE_SIZE for guaranteed allocation. 632 */ 633 634 cont = size; 635 size = ALIGN(size, psb->crypto_align_size); 636 pad = size - cont; 637 638 size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added; 639 640 cont = sizeof(struct netfs_trans) + size_no_trans; 641 642 num = (PAGE_SIZE - cont)/sizeof(struct page *); 643 644 if (nr > num) 645 nr = num; 646 647 t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO); 648 if (!t) 649 goto err_out_exit; 650 651 t->iovec.iov_base = (void *)(t + 1); 652 t->pages = (struct page **)(t->iovec.iov_base + size_no_trans); 653 654 /* 655 * Reserving space for transaction header. 656 */ 657 t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added; 658 659 netfs_trans_init_static(t, nr, size_no_trans); 660 661 t->flags = flags; 662 t->psb = psb; 663 664 cmd = (struct netfs_cmd *)t->iovec.iov_base; 665 666 cmd->size = size; 667 cmd->cpad = pad; 668 cmd->csize = crypto_added; 669 670 dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, " 671 "page_num: %u, base: %p, pages: %p.\n", 672 __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr, 673 t->iovec.iov_base, t->pages); 674 675 return t; 676 677err_out_exit: 678 return NULL; 679} 680 681int netfs_trans_init(void) 682{ 683 int err = -ENOMEM; 684 685 netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst), 686 0, 0, NULL); 687 if (!netfs_trans_dst) 688 goto err_out_exit; 689 690 netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst); 691 if (!netfs_trans_dst_pool) 692 goto err_out_free; 693 694 return 0; 695 696err_out_free: 697 kmem_cache_destroy(netfs_trans_dst); 698err_out_exit: 699 return err; 700} 701 702void netfs_trans_exit(void) 703{ 704 mempool_destroy(netfs_trans_dst_pool); 705 kmem_cache_destroy(netfs_trans_dst); 706}