diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/tree-log.c | 48 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 16 | ||||
| -rw-r--r-- | fs/ecryptfs/miscdev.c | 14 | ||||
| -rw-r--r-- | fs/inode.c | 2 | ||||
| -rw-r--r-- | fs/namespace.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4client.c | 45 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 8 | ||||
| -rw-r--r-- | fs/proc/generic.c | 119 |
9 files changed, 185 insertions, 70 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 451fad96ecd1..ef96381569a4 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -317,6 +317,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
| 317 | unsigned long src_ptr; | 317 | unsigned long src_ptr; |
| 318 | unsigned long dst_ptr; | 318 | unsigned long dst_ptr; |
| 319 | int overwrite_root = 0; | 319 | int overwrite_root = 0; |
| 320 | bool inode_item = key->type == BTRFS_INODE_ITEM_KEY; | ||
| 320 | 321 | ||
| 321 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 322 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
| 322 | overwrite_root = 1; | 323 | overwrite_root = 1; |
| @@ -326,6 +327,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
| 326 | 327 | ||
| 327 | /* look for the key in the destination tree */ | 328 | /* look for the key in the destination tree */ |
| 328 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 329 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
| 330 | if (ret < 0) | ||
| 331 | return ret; | ||
| 332 | |||
| 329 | if (ret == 0) { | 333 | if (ret == 0) { |
| 330 | char *src_copy; | 334 | char *src_copy; |
| 331 | char *dst_copy; | 335 | char *dst_copy; |
| @@ -367,6 +371,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, | |||
| 367 | return 0; | 371 | return 0; |
| 368 | } | 372 | } |
| 369 | 373 | ||
| 374 | /* | ||
| 375 | * We need to load the old nbytes into the inode so when we | ||
| 376 | * replay the extents we've logged we get the right nbytes. | ||
| 377 | */ | ||
| 378 | if (inode_item) { | ||
| 379 | struct btrfs_inode_item *item; | ||
| 380 | u64 nbytes; | ||
| 381 | |||
| 382 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
| 383 | struct btrfs_inode_item); | ||
| 384 | nbytes = btrfs_inode_nbytes(path->nodes[0], item); | ||
| 385 | item = btrfs_item_ptr(eb, slot, | ||
| 386 | struct btrfs_inode_item); | ||
| 387 | btrfs_set_inode_nbytes(eb, item, nbytes); | ||
| 388 | } | ||
| 389 | } else if (inode_item) { | ||
| 390 | struct btrfs_inode_item *item; | ||
| 391 | |||
| 392 | /* | ||
| 393 | * New inode, set nbytes to 0 so that the nbytes comes out | ||
| 394 | * properly when we replay the extents. | ||
| 395 | */ | ||
| 396 | item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); | ||
| 397 | btrfs_set_inode_nbytes(eb, item, 0); | ||
| 370 | } | 398 | } |
| 371 | insert: | 399 | insert: |
| 372 | btrfs_release_path(path); | 400 | btrfs_release_path(path); |
| @@ -486,7 +514,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
| 486 | int found_type; | 514 | int found_type; |
| 487 | u64 extent_end; | 515 | u64 extent_end; |
| 488 | u64 start = key->offset; | 516 | u64 start = key->offset; |
| 489 | u64 saved_nbytes; | 517 | u64 nbytes = 0; |
| 490 | struct btrfs_file_extent_item *item; | 518 | struct btrfs_file_extent_item *item; |
| 491 | struct inode *inode = NULL; | 519 | struct inode *inode = NULL; |
| 492 | unsigned long size; | 520 | unsigned long size; |
| @@ -496,10 +524,19 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
| 496 | found_type = btrfs_file_extent_type(eb, item); | 524 | found_type = btrfs_file_extent_type(eb, item); |
| 497 | 525 | ||
| 498 | if (found_type == BTRFS_FILE_EXTENT_REG || | 526 | if (found_type == BTRFS_FILE_EXTENT_REG || |
| 499 | found_type == BTRFS_FILE_EXTENT_PREALLOC) | 527 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
| 500 | extent_end = start + btrfs_file_extent_num_bytes(eb, item); | 528 | nbytes = btrfs_file_extent_num_bytes(eb, item); |
| 501 | else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 529 | extent_end = start + nbytes; |
| 530 | |||
| 531 | /* | ||
| 532 | * We don't add to the inodes nbytes if we are prealloc or a | ||
| 533 | * hole. | ||
| 534 | */ | ||
| 535 | if (btrfs_file_extent_disk_bytenr(eb, item) == 0) | ||
| 536 | nbytes = 0; | ||
| 537 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | ||
| 502 | size = btrfs_file_extent_inline_len(eb, item); | 538 | size = btrfs_file_extent_inline_len(eb, item); |
| 539 | nbytes = btrfs_file_extent_ram_bytes(eb, item); | ||
| 503 | extent_end = ALIGN(start + size, root->sectorsize); | 540 | extent_end = ALIGN(start + size, root->sectorsize); |
| 504 | } else { | 541 | } else { |
| 505 | ret = 0; | 542 | ret = 0; |
| @@ -548,7 +585,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
| 548 | } | 585 | } |
| 549 | btrfs_release_path(path); | 586 | btrfs_release_path(path); |
| 550 | 587 | ||
| 551 | saved_nbytes = inode_get_bytes(inode); | ||
| 552 | /* drop any overlapping extents */ | 588 | /* drop any overlapping extents */ |
| 553 | ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1); | 589 | ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1); |
| 554 | BUG_ON(ret); | 590 | BUG_ON(ret); |
| @@ -635,7 +671,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
| 635 | BUG_ON(ret); | 671 | BUG_ON(ret); |
| 636 | } | 672 | } |
| 637 | 673 | ||
| 638 | inode_set_bytes(inode, saved_nbytes); | 674 | inode_add_bytes(inode, nbytes); |
| 639 | ret = btrfs_update_inode(trans, root, inode); | 675 | ret = btrfs_update_inode(trans, root, inode); |
| 640 | out: | 676 | out: |
| 641 | if (inode) | 677 | if (inode) |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 991c63c6bdd0..21b3a291c327 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -1575,14 +1575,24 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1575 | } | 1575 | } |
| 1576 | break; | 1576 | break; |
| 1577 | case Opt_blank_pass: | 1577 | case Opt_blank_pass: |
| 1578 | vol->password = NULL; | ||
| 1579 | break; | ||
| 1580 | case Opt_pass: | ||
| 1581 | /* passwords have to be handled differently | 1578 | /* passwords have to be handled differently |
| 1582 | * to allow the character used for deliminator | 1579 | * to allow the character used for deliminator |
| 1583 | * to be passed within them | 1580 | * to be passed within them |
| 1584 | */ | 1581 | */ |
| 1585 | 1582 | ||
| 1583 | /* | ||
| 1584 | * Check if this is a case where the password | ||
| 1585 | * starts with a delimiter | ||
| 1586 | */ | ||
| 1587 | tmp_end = strchr(data, '='); | ||
| 1588 | tmp_end++; | ||
| 1589 | if (!(tmp_end < end && tmp_end[1] == delim)) { | ||
| 1590 | /* No it is not. Set the password to NULL */ | ||
| 1591 | vol->password = NULL; | ||
| 1592 | break; | ||
| 1593 | } | ||
| 1594 | /* Yes it is. Drop down to Opt_pass below.*/ | ||
| 1595 | case Opt_pass: | ||
| 1586 | /* Obtain the value string */ | 1596 | /* Obtain the value string */ |
| 1587 | value = strchr(data, '='); | 1597 | value = strchr(data, '='); |
| 1588 | value++; | 1598 | value++; |
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 412e6eda25f8..e4141f257495 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
| @@ -80,13 +80,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
| 80 | int rc; | 80 | int rc; |
| 81 | 81 | ||
| 82 | mutex_lock(&ecryptfs_daemon_hash_mux); | 82 | mutex_lock(&ecryptfs_daemon_hash_mux); |
| 83 | rc = try_module_get(THIS_MODULE); | ||
| 84 | if (rc == 0) { | ||
| 85 | rc = -EIO; | ||
| 86 | printk(KERN_ERR "%s: Error attempting to increment module use " | ||
| 87 | "count; rc = [%d]\n", __func__, rc); | ||
| 88 | goto out_unlock_daemon_list; | ||
| 89 | } | ||
| 90 | rc = ecryptfs_find_daemon_by_euid(&daemon); | 83 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
| 91 | if (!rc) { | 84 | if (!rc) { |
| 92 | rc = -EINVAL; | 85 | rc = -EINVAL; |
| @@ -96,7 +89,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
| 96 | if (rc) { | 89 | if (rc) { |
| 97 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " | 90 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " |
| 98 | "rc = [%d]\n", __func__, rc); | 91 | "rc = [%d]\n", __func__, rc); |
| 99 | goto out_module_put_unlock_daemon_list; | 92 | goto out_unlock_daemon_list; |
| 100 | } | 93 | } |
| 101 | mutex_lock(&daemon->mux); | 94 | mutex_lock(&daemon->mux); |
| 102 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { | 95 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { |
| @@ -108,9 +101,6 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
| 108 | atomic_inc(&ecryptfs_num_miscdev_opens); | 101 | atomic_inc(&ecryptfs_num_miscdev_opens); |
| 109 | out_unlock_daemon: | 102 | out_unlock_daemon: |
| 110 | mutex_unlock(&daemon->mux); | 103 | mutex_unlock(&daemon->mux); |
| 111 | out_module_put_unlock_daemon_list: | ||
| 112 | if (rc) | ||
| 113 | module_put(THIS_MODULE); | ||
| 114 | out_unlock_daemon_list: | 104 | out_unlock_daemon_list: |
| 115 | mutex_unlock(&ecryptfs_daemon_hash_mux); | 105 | mutex_unlock(&ecryptfs_daemon_hash_mux); |
| 116 | return rc; | 106 | return rc; |
| @@ -147,7 +137,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) | |||
| 147 | "bug.\n", __func__, rc); | 137 | "bug.\n", __func__, rc); |
| 148 | BUG(); | 138 | BUG(); |
| 149 | } | 139 | } |
| 150 | module_put(THIS_MODULE); | ||
| 151 | return rc; | 140 | return rc; |
| 152 | } | 141 | } |
| 153 | 142 | ||
| @@ -471,6 +460,7 @@ out_free: | |||
| 471 | 460 | ||
| 472 | 461 | ||
| 473 | static const struct file_operations ecryptfs_miscdev_fops = { | 462 | static const struct file_operations ecryptfs_miscdev_fops = { |
| 463 | .owner = THIS_MODULE, | ||
| 474 | .open = ecryptfs_miscdev_open, | 464 | .open = ecryptfs_miscdev_open, |
| 475 | .poll = ecryptfs_miscdev_poll, | 465 | .poll = ecryptfs_miscdev_poll, |
| 476 | .read = ecryptfs_miscdev_read, | 466 | .read = ecryptfs_miscdev_read, |
diff --git a/fs/inode.c b/fs/inode.c index f5f7c06c36fb..a898b3d43ccf 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -725,7 +725,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan) | |||
| 725 | * inode to the back of the list so we don't spin on it. | 725 | * inode to the back of the list so we don't spin on it. |
| 726 | */ | 726 | */ |
| 727 | if (!spin_trylock(&inode->i_lock)) { | 727 | if (!spin_trylock(&inode->i_lock)) { |
| 728 | list_move_tail(&inode->i_lru, &sb->s_inode_lru); | 728 | list_move(&inode->i_lru, &sb->s_inode_lru); |
| 729 | continue; | 729 | continue; |
| 730 | } | 730 | } |
| 731 | 731 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index d581e45c0a9f..341d3f564082 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1690,7 +1690,7 @@ static int do_loopback(struct path *path, const char *old_name, | |||
| 1690 | 1690 | ||
| 1691 | if (IS_ERR(mnt)) { | 1691 | if (IS_ERR(mnt)) { |
| 1692 | err = PTR_ERR(mnt); | 1692 | err = PTR_ERR(mnt); |
| 1693 | goto out; | 1693 | goto out2; |
| 1694 | } | 1694 | } |
| 1695 | 1695 | ||
| 1696 | err = graft_tree(mnt, path); | 1696 | err = graft_tree(mnt, path); |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index ac4fc9a8fdbc..66b6664dcd4c 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -300,7 +300,7 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
| 300 | struct rpc_cred *cred) | 300 | struct rpc_cred *cred) |
| 301 | { | 301 | { |
| 302 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); | 302 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
| 303 | struct nfs_client *pos, *n, *prev = NULL; | 303 | struct nfs_client *pos, *prev = NULL; |
| 304 | struct nfs4_setclientid_res clid = { | 304 | struct nfs4_setclientid_res clid = { |
| 305 | .clientid = new->cl_clientid, | 305 | .clientid = new->cl_clientid, |
| 306 | .confirm = new->cl_confirm, | 306 | .confirm = new->cl_confirm, |
| @@ -308,10 +308,23 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
| 308 | int status = -NFS4ERR_STALE_CLIENTID; | 308 | int status = -NFS4ERR_STALE_CLIENTID; |
| 309 | 309 | ||
| 310 | spin_lock(&nn->nfs_client_lock); | 310 | spin_lock(&nn->nfs_client_lock); |
| 311 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { | 311 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
| 312 | /* If "pos" isn't marked ready, we can't trust the | 312 | /* If "pos" isn't marked ready, we can't trust the |
| 313 | * remaining fields in "pos" */ | 313 | * remaining fields in "pos" */ |
| 314 | if (pos->cl_cons_state < NFS_CS_READY) | 314 | if (pos->cl_cons_state > NFS_CS_READY) { |
| 315 | atomic_inc(&pos->cl_count); | ||
| 316 | spin_unlock(&nn->nfs_client_lock); | ||
| 317 | |||
| 318 | if (prev) | ||
| 319 | nfs_put_client(prev); | ||
| 320 | prev = pos; | ||
| 321 | |||
| 322 | status = nfs_wait_client_init_complete(pos); | ||
| 323 | spin_lock(&nn->nfs_client_lock); | ||
| 324 | if (status < 0) | ||
| 325 | continue; | ||
| 326 | } | ||
| 327 | if (pos->cl_cons_state != NFS_CS_READY) | ||
| 315 | continue; | 328 | continue; |
| 316 | 329 | ||
| 317 | if (pos->rpc_ops != new->rpc_ops) | 330 | if (pos->rpc_ops != new->rpc_ops) |
| @@ -423,16 +436,16 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 423 | struct rpc_cred *cred) | 436 | struct rpc_cred *cred) |
| 424 | { | 437 | { |
| 425 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); | 438 | struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); |
| 426 | struct nfs_client *pos, *n, *prev = NULL; | 439 | struct nfs_client *pos, *prev = NULL; |
| 427 | int status = -NFS4ERR_STALE_CLIENTID; | 440 | int status = -NFS4ERR_STALE_CLIENTID; |
| 428 | 441 | ||
| 429 | spin_lock(&nn->nfs_client_lock); | 442 | spin_lock(&nn->nfs_client_lock); |
| 430 | list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { | 443 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
| 431 | /* If "pos" isn't marked ready, we can't trust the | 444 | /* If "pos" isn't marked ready, we can't trust the |
| 432 | * remaining fields in "pos", especially the client | 445 | * remaining fields in "pos", especially the client |
| 433 | * ID and serverowner fields. Wait for CREATE_SESSION | 446 | * ID and serverowner fields. Wait for CREATE_SESSION |
| 434 | * to finish. */ | 447 | * to finish. */ |
| 435 | if (pos->cl_cons_state < NFS_CS_READY) { | 448 | if (pos->cl_cons_state > NFS_CS_READY) { |
| 436 | atomic_inc(&pos->cl_count); | 449 | atomic_inc(&pos->cl_count); |
| 437 | spin_unlock(&nn->nfs_client_lock); | 450 | spin_unlock(&nn->nfs_client_lock); |
| 438 | 451 | ||
| @@ -440,18 +453,17 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 440 | nfs_put_client(prev); | 453 | nfs_put_client(prev); |
| 441 | prev = pos; | 454 | prev = pos; |
| 442 | 455 | ||
| 443 | nfs4_schedule_lease_recovery(pos); | ||
| 444 | status = nfs_wait_client_init_complete(pos); | 456 | status = nfs_wait_client_init_complete(pos); |
| 445 | if (status < 0) { | 457 | if (status == 0) { |
| 446 | nfs_put_client(pos); | 458 | nfs4_schedule_lease_recovery(pos); |
| 447 | spin_lock(&nn->nfs_client_lock); | 459 | status = nfs4_wait_clnt_recover(pos); |
| 448 | continue; | ||
| 449 | } | 460 | } |
| 450 | status = pos->cl_cons_state; | ||
| 451 | spin_lock(&nn->nfs_client_lock); | 461 | spin_lock(&nn->nfs_client_lock); |
| 452 | if (status < 0) | 462 | if (status < 0) |
| 453 | continue; | 463 | continue; |
| 454 | } | 464 | } |
| 465 | if (pos->cl_cons_state != NFS_CS_READY) | ||
| 466 | continue; | ||
| 455 | 467 | ||
| 456 | if (pos->rpc_ops != new->rpc_ops) | 468 | if (pos->rpc_ops != new->rpc_ops) |
| 457 | continue; | 469 | continue; |
| @@ -469,17 +481,18 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 469 | continue; | 481 | continue; |
| 470 | 482 | ||
| 471 | atomic_inc(&pos->cl_count); | 483 | atomic_inc(&pos->cl_count); |
| 472 | spin_unlock(&nn->nfs_client_lock); | 484 | *result = pos; |
| 485 | status = 0; | ||
| 473 | dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", | 486 | dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", |
| 474 | __func__, pos, atomic_read(&pos->cl_count)); | 487 | __func__, pos, atomic_read(&pos->cl_count)); |
| 475 | 488 | break; | |
| 476 | *result = pos; | ||
| 477 | return 0; | ||
| 478 | } | 489 | } |
| 479 | 490 | ||
| 480 | /* No matching nfs_client found. */ | 491 | /* No matching nfs_client found. */ |
| 481 | spin_unlock(&nn->nfs_client_lock); | 492 | spin_unlock(&nn->nfs_client_lock); |
| 482 | dprintk("NFS: <-- %s status = %d\n", __func__, status); | 493 | dprintk("NFS: <-- %s status = %d\n", __func__, status); |
| 494 | if (prev) | ||
| 495 | nfs_put_client(prev); | ||
| 483 | return status; | 496 | return status; |
| 484 | } | 497 | } |
| 485 | #endif /* CONFIG_NFS_V4_1 */ | 498 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 26431cf62ddb..0ad025eb523b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1046,6 +1046,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
| 1046 | /* Save the delegation */ | 1046 | /* Save the delegation */ |
| 1047 | nfs4_stateid_copy(&stateid, &delegation->stateid); | 1047 | nfs4_stateid_copy(&stateid, &delegation->stateid); |
| 1048 | rcu_read_unlock(); | 1048 | rcu_read_unlock(); |
| 1049 | nfs_release_seqid(opendata->o_arg.seqid); | ||
| 1049 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); | 1050 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); |
| 1050 | if (ret != 0) | 1051 | if (ret != 0) |
| 1051 | goto out; | 1052 | goto out; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6ace365c6334..d41a3518509f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -1886,7 +1886,13 @@ again: | |||
| 1886 | status = PTR_ERR(clnt); | 1886 | status = PTR_ERR(clnt); |
| 1887 | break; | 1887 | break; |
| 1888 | } | 1888 | } |
| 1889 | clp->cl_rpcclient = clnt; | 1889 | /* Note: this is safe because we haven't yet marked the |
| 1890 | * client as ready, so we are the only user of | ||
| 1891 | * clp->cl_rpcclient | ||
| 1892 | */ | ||
| 1893 | clnt = xchg(&clp->cl_rpcclient, clnt); | ||
| 1894 | rpc_shutdown_client(clnt); | ||
| 1895 | clnt = clp->cl_rpcclient; | ||
| 1890 | goto again; | 1896 | goto again; |
| 1891 | 1897 | ||
| 1892 | case -NFS4ERR_MINOR_VERS_MISMATCH: | 1898 | case -NFS4ERR_MINOR_VERS_MISMATCH: |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 4b3b3ffb52f1..21e1a8f1659d 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -755,37 +755,8 @@ void pde_put(struct proc_dir_entry *pde) | |||
| 755 | free_proc_entry(pde); | 755 | free_proc_entry(pde); |
| 756 | } | 756 | } |
| 757 | 757 | ||
| 758 | /* | 758 | static void entry_rundown(struct proc_dir_entry *de) |
| 759 | * Remove a /proc entry and free it if it's not currently in use. | ||
| 760 | */ | ||
| 761 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | ||
| 762 | { | 759 | { |
| 763 | struct proc_dir_entry **p; | ||
| 764 | struct proc_dir_entry *de = NULL; | ||
| 765 | const char *fn = name; | ||
| 766 | unsigned int len; | ||
| 767 | |||
| 768 | spin_lock(&proc_subdir_lock); | ||
| 769 | if (__xlate_proc_name(name, &parent, &fn) != 0) { | ||
| 770 | spin_unlock(&proc_subdir_lock); | ||
| 771 | return; | ||
| 772 | } | ||
| 773 | len = strlen(fn); | ||
| 774 | |||
| 775 | for (p = &parent->subdir; *p; p=&(*p)->next ) { | ||
| 776 | if (proc_match(len, fn, *p)) { | ||
| 777 | de = *p; | ||
| 778 | *p = de->next; | ||
| 779 | de->next = NULL; | ||
| 780 | break; | ||
| 781 | } | ||
| 782 | } | ||
| 783 | spin_unlock(&proc_subdir_lock); | ||
| 784 | if (!de) { | ||
| 785 | WARN(1, "name '%s'\n", name); | ||
| 786 | return; | ||
| 787 | } | ||
| 788 | |||
| 789 | spin_lock(&de->pde_unload_lock); | 760 | spin_lock(&de->pde_unload_lock); |
| 790 | /* | 761 | /* |
| 791 | * Stop accepting new callers into module. If you're | 762 | * Stop accepting new callers into module. If you're |
| @@ -817,6 +788,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
| 817 | spin_lock(&de->pde_unload_lock); | 788 | spin_lock(&de->pde_unload_lock); |
| 818 | } | 789 | } |
| 819 | spin_unlock(&de->pde_unload_lock); | 790 | spin_unlock(&de->pde_unload_lock); |
| 791 | } | ||
| 792 | |||
| 793 | /* | ||
| 794 | * Remove a /proc entry and free it if it's not currently in use. | ||
| 795 | */ | ||
| 796 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | ||
| 797 | { | ||
| 798 | struct proc_dir_entry **p; | ||
| 799 | struct proc_dir_entry *de = NULL; | ||
| 800 | const char *fn = name; | ||
| 801 | unsigned int len; | ||
| 802 | |||
| 803 | spin_lock(&proc_subdir_lock); | ||
| 804 | if (__xlate_proc_name(name, &parent, &fn) != 0) { | ||
| 805 | spin_unlock(&proc_subdir_lock); | ||
| 806 | return; | ||
| 807 | } | ||
| 808 | len = strlen(fn); | ||
| 809 | |||
| 810 | for (p = &parent->subdir; *p; p=&(*p)->next ) { | ||
| 811 | if (proc_match(len, fn, *p)) { | ||
| 812 | de = *p; | ||
| 813 | *p = de->next; | ||
| 814 | de->next = NULL; | ||
| 815 | break; | ||
| 816 | } | ||
| 817 | } | ||
| 818 | spin_unlock(&proc_subdir_lock); | ||
| 819 | if (!de) { | ||
| 820 | WARN(1, "name '%s'\n", name); | ||
| 821 | return; | ||
| 822 | } | ||
| 823 | |||
| 824 | entry_rundown(de); | ||
| 820 | 825 | ||
| 821 | if (S_ISDIR(de->mode)) | 826 | if (S_ISDIR(de->mode)) |
| 822 | parent->nlink--; | 827 | parent->nlink--; |
| @@ -827,3 +832,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
| 827 | pde_put(de); | 832 | pde_put(de); |
| 828 | } | 833 | } |
| 829 | EXPORT_SYMBOL(remove_proc_entry); | 834 | EXPORT_SYMBOL(remove_proc_entry); |
| 835 | |||
| 836 | int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) | ||
| 837 | { | ||
| 838 | struct proc_dir_entry **p; | ||
| 839 | struct proc_dir_entry *root = NULL, *de, *next; | ||
| 840 | const char *fn = name; | ||
| 841 | unsigned int len; | ||
| 842 | |||
| 843 | spin_lock(&proc_subdir_lock); | ||
| 844 | if (__xlate_proc_name(name, &parent, &fn) != 0) { | ||
| 845 | spin_unlock(&proc_subdir_lock); | ||
| 846 | return -ENOENT; | ||
| 847 | } | ||
| 848 | len = strlen(fn); | ||
| 849 | |||
| 850 | for (p = &parent->subdir; *p; p=&(*p)->next ) { | ||
| 851 | if (proc_match(len, fn, *p)) { | ||
| 852 | root = *p; | ||
| 853 | *p = root->next; | ||
| 854 | root->next = NULL; | ||
| 855 | break; | ||
| 856 | } | ||
| 857 | } | ||
| 858 | if (!root) { | ||
| 859 | spin_unlock(&proc_subdir_lock); | ||
| 860 | return -ENOENT; | ||
| 861 | } | ||
| 862 | de = root; | ||
| 863 | while (1) { | ||
| 864 | next = de->subdir; | ||
| 865 | if (next) { | ||
| 866 | de->subdir = next->next; | ||
| 867 | next->next = NULL; | ||
| 868 | de = next; | ||
| 869 | continue; | ||
| 870 | } | ||
| 871 | spin_unlock(&proc_subdir_lock); | ||
| 872 | |||
| 873 | entry_rundown(de); | ||
| 874 | next = de->parent; | ||
| 875 | if (S_ISDIR(de->mode)) | ||
| 876 | next->nlink--; | ||
| 877 | de->nlink = 0; | ||
| 878 | if (de == root) | ||
| 879 | break; | ||
| 880 | pde_put(de); | ||
| 881 | |||
| 882 | spin_lock(&proc_subdir_lock); | ||
| 883 | de = next; | ||
| 884 | } | ||
| 885 | pde_put(root); | ||
| 886 | return 0; | ||
| 887 | } | ||
| 888 | EXPORT_SYMBOL(remove_proc_subtree); | ||
