diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/blocklayout/blocklayoutdm.c | 4 | ||||
| -rw-r--r-- | fs/nfs/idmap.c | 13 | ||||
| -rw-r--r-- | fs/nfs/nfs4filelayout.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 16 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 81 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 6 |
6 files changed, 89 insertions, 32 deletions
diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c index 737d839bc17b..6fc7b5cae92b 100644 --- a/fs/nfs/blocklayout/blocklayoutdm.c +++ b/fs/nfs/blocklayout/blocklayoutdm.c | |||
| @@ -55,7 +55,8 @@ static void dev_remove(struct net *net, dev_t dev) | |||
| 55 | 55 | ||
| 56 | bl_pipe_msg.bl_wq = &nn->bl_wq; | 56 | bl_pipe_msg.bl_wq = &nn->bl_wq; |
| 57 | memset(msg, 0, sizeof(*msg)); | 57 | memset(msg, 0, sizeof(*msg)); |
| 58 | msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS); | 58 | msg->len = sizeof(bl_msg) + bl_msg.totallen; |
| 59 | msg->data = kzalloc(msg->len, GFP_NOFS); | ||
| 59 | if (!msg->data) | 60 | if (!msg->data) |
| 60 | goto out; | 61 | goto out; |
| 61 | 62 | ||
| @@ -66,7 +67,6 @@ static void dev_remove(struct net *net, dev_t dev) | |||
| 66 | memcpy(msg->data, &bl_msg, sizeof(bl_msg)); | 67 | memcpy(msg->data, &bl_msg, sizeof(bl_msg)); |
| 67 | dataptr = (uint8_t *) msg->data; | 68 | dataptr = (uint8_t *) msg->data; |
| 68 | memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request)); | 69 | memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request)); |
| 69 | msg->len = sizeof(bl_msg) + bl_msg.totallen; | ||
| 70 | 70 | ||
| 71 | add_wait_queue(&nn->bl_wq, &wq); | 71 | add_wait_queue(&nn->bl_wq, &wq); |
| 72 | if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) { | 72 | if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) { |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index dc0f98dfa717..c516da5873fd 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -726,9 +726,9 @@ out1: | |||
| 726 | return ret; | 726 | return ret; |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data) | 729 | static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen) |
| 730 | { | 730 | { |
| 731 | return key_instantiate_and_link(key, data, strlen(data) + 1, | 731 | return key_instantiate_and_link(key, data, datalen, |
| 732 | id_resolver_cache->thread_keyring, | 732 | id_resolver_cache->thread_keyring, |
| 733 | authkey); | 733 | authkey); |
| 734 | } | 734 | } |
| @@ -738,6 +738,7 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im, | |||
| 738 | struct key *key, struct key *authkey) | 738 | struct key *key, struct key *authkey) |
| 739 | { | 739 | { |
| 740 | char id_str[NFS_UINT_MAXLEN]; | 740 | char id_str[NFS_UINT_MAXLEN]; |
| 741 | size_t len; | ||
| 741 | int ret = -ENOKEY; | 742 | int ret = -ENOKEY; |
| 742 | 743 | ||
| 743 | /* ret = -ENOKEY */ | 744 | /* ret = -ENOKEY */ |
| @@ -747,13 +748,15 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im, | |||
| 747 | case IDMAP_CONV_NAMETOID: | 748 | case IDMAP_CONV_NAMETOID: |
| 748 | if (strcmp(upcall->im_name, im->im_name) != 0) | 749 | if (strcmp(upcall->im_name, im->im_name) != 0) |
| 749 | break; | 750 | break; |
| 750 | sprintf(id_str, "%d", im->im_id); | 751 | /* Note: here we store the NUL terminator too */ |
| 751 | ret = nfs_idmap_instantiate(key, authkey, id_str); | 752 | len = sprintf(id_str, "%d", im->im_id) + 1; |
| 753 | ret = nfs_idmap_instantiate(key, authkey, id_str, len); | ||
| 752 | break; | 754 | break; |
| 753 | case IDMAP_CONV_IDTONAME: | 755 | case IDMAP_CONV_IDTONAME: |
| 754 | if (upcall->im_id != im->im_id) | 756 | if (upcall->im_id != im->im_id) |
| 755 | break; | 757 | break; |
| 756 | ret = nfs_idmap_instantiate(key, authkey, im->im_name); | 758 | len = strlen(im->im_name); |
| 759 | ret = nfs_idmap_instantiate(key, authkey, im->im_name, len); | ||
| 757 | break; | 760 | break; |
| 758 | default: | 761 | default: |
| 759 | ret = -EINVAL; | 762 | ret = -EINVAL; |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 49eeb044c109..4fb234d3aefb 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -129,7 +129,6 @@ static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo) | |||
| 129 | { | 129 | { |
| 130 | if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | 130 | if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) |
| 131 | return; | 131 | return; |
| 132 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); | ||
| 133 | pnfs_return_layout(inode); | 132 | pnfs_return_layout(inode); |
| 134 | } | 133 | } |
| 135 | 134 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b2671cb0f901..26431cf62ddb 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2632,7 +2632,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 2632 | int status; | 2632 | int status; |
| 2633 | 2633 | ||
| 2634 | if (pnfs_ld_layoutret_on_setattr(inode)) | 2634 | if (pnfs_ld_layoutret_on_setattr(inode)) |
| 2635 | pnfs_return_layout(inode); | 2635 | pnfs_commit_and_return_layout(inode); |
| 2636 | 2636 | ||
| 2637 | nfs_fattr_init(fattr); | 2637 | nfs_fattr_init(fattr); |
| 2638 | 2638 | ||
| @@ -6416,22 +6416,8 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
| 6416 | static void nfs4_layoutcommit_release(void *calldata) | 6416 | static void nfs4_layoutcommit_release(void *calldata) |
| 6417 | { | 6417 | { |
| 6418 | struct nfs4_layoutcommit_data *data = calldata; | 6418 | struct nfs4_layoutcommit_data *data = calldata; |
| 6419 | struct pnfs_layout_segment *lseg, *tmp; | ||
| 6420 | unsigned long *bitlock = &NFS_I(data->args.inode)->flags; | ||
| 6421 | 6419 | ||
| 6422 | pnfs_cleanup_layoutcommit(data); | 6420 | pnfs_cleanup_layoutcommit(data); |
| 6423 | /* Matched by references in pnfs_set_layoutcommit */ | ||
| 6424 | list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) { | ||
| 6425 | list_del_init(&lseg->pls_lc_list); | ||
| 6426 | if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, | ||
| 6427 | &lseg->pls_flags)) | ||
| 6428 | pnfs_put_lseg(lseg); | ||
| 6429 | } | ||
| 6430 | |||
| 6431 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); | ||
| 6432 | smp_mb__after_clear_bit(); | ||
| 6433 | wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING); | ||
| 6434 | |||
| 6435 | put_rpccred(data->cred); | 6421 | put_rpccred(data->cred); |
| 6436 | kfree(data); | 6422 | kfree(data); |
| 6437 | } | 6423 | } |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 48ac5aad6258..4bdffe0ba025 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_range *lseg_range, | |||
| 417 | lo_seg_intersecting(lseg_range, recall_range); | 417 | lo_seg_intersecting(lseg_range, recall_range); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg, | ||
| 421 | struct list_head *tmp_list) | ||
| 422 | { | ||
| 423 | if (!atomic_dec_and_test(&lseg->pls_refcount)) | ||
| 424 | return false; | ||
| 425 | pnfs_layout_remove_lseg(lseg->pls_layout, lseg); | ||
| 426 | list_add(&lseg->pls_list, tmp_list); | ||
| 427 | return true; | ||
| 428 | } | ||
| 429 | |||
| 420 | /* Returns 1 if lseg is removed from list, 0 otherwise */ | 430 | /* Returns 1 if lseg is removed from list, 0 otherwise */ |
| 421 | static int mark_lseg_invalid(struct pnfs_layout_segment *lseg, | 431 | static int mark_lseg_invalid(struct pnfs_layout_segment *lseg, |
| 422 | struct list_head *tmp_list) | 432 | struct list_head *tmp_list) |
| @@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg, | |||
| 430 | */ | 440 | */ |
| 431 | dprintk("%s: lseg %p ref %d\n", __func__, lseg, | 441 | dprintk("%s: lseg %p ref %d\n", __func__, lseg, |
| 432 | atomic_read(&lseg->pls_refcount)); | 442 | atomic_read(&lseg->pls_refcount)); |
| 433 | if (atomic_dec_and_test(&lseg->pls_refcount)) { | 443 | if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list)) |
| 434 | pnfs_layout_remove_lseg(lseg->pls_layout, lseg); | ||
| 435 | list_add(&lseg->pls_list, tmp_list); | ||
| 436 | rv = 1; | 444 | rv = 1; |
| 437 | } | ||
| 438 | } | 445 | } |
| 439 | return rv; | 446 | return rv; |
| 440 | } | 447 | } |
| @@ -777,6 +784,21 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
| 777 | return lseg; | 784 | return lseg; |
| 778 | } | 785 | } |
| 779 | 786 | ||
| 787 | static void pnfs_clear_layoutcommit(struct inode *inode, | ||
| 788 | struct list_head *head) | ||
| 789 | { | ||
| 790 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 791 | struct pnfs_layout_segment *lseg, *tmp; | ||
| 792 | |||
| 793 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) | ||
| 794 | return; | ||
| 795 | list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) { | ||
| 796 | if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) | ||
| 797 | continue; | ||
| 798 | pnfs_lseg_dec_and_remove_zero(lseg, head); | ||
| 799 | } | ||
| 800 | } | ||
| 801 | |||
| 780 | /* | 802 | /* |
| 781 | * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr | 803 | * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr |
| 782 | * when the layout segment list is empty. | 804 | * when the layout segment list is empty. |
| @@ -808,6 +830,7 @@ _pnfs_return_layout(struct inode *ino) | |||
| 808 | /* Reference matched in nfs4_layoutreturn_release */ | 830 | /* Reference matched in nfs4_layoutreturn_release */ |
| 809 | pnfs_get_layout_hdr(lo); | 831 | pnfs_get_layout_hdr(lo); |
| 810 | empty = list_empty(&lo->plh_segs); | 832 | empty = list_empty(&lo->plh_segs); |
| 833 | pnfs_clear_layoutcommit(ino, &tmp_list); | ||
| 811 | pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); | 834 | pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL); |
| 812 | /* Don't send a LAYOUTRETURN if list was initially empty */ | 835 | /* Don't send a LAYOUTRETURN if list was initially empty */ |
| 813 | if (empty) { | 836 | if (empty) { |
| @@ -820,8 +843,6 @@ _pnfs_return_layout(struct inode *ino) | |||
| 820 | spin_unlock(&ino->i_lock); | 843 | spin_unlock(&ino->i_lock); |
| 821 | pnfs_free_lseg_list(&tmp_list); | 844 | pnfs_free_lseg_list(&tmp_list); |
| 822 | 845 | ||
| 823 | WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)); | ||
| 824 | |||
| 825 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); | 846 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); |
| 826 | if (unlikely(lrp == NULL)) { | 847 | if (unlikely(lrp == NULL)) { |
| 827 | status = -ENOMEM; | 848 | status = -ENOMEM; |
| @@ -845,6 +866,33 @@ out: | |||
| 845 | } | 866 | } |
| 846 | EXPORT_SYMBOL_GPL(_pnfs_return_layout); | 867 | EXPORT_SYMBOL_GPL(_pnfs_return_layout); |
| 847 | 868 | ||
| 869 | int | ||
| 870 | pnfs_commit_and_return_layout(struct inode *inode) | ||
| 871 | { | ||
| 872 | struct pnfs_layout_hdr *lo; | ||
| 873 | int ret; | ||
| 874 | |||
| 875 | spin_lock(&inode->i_lock); | ||
| 876 | lo = NFS_I(inode)->layout; | ||
| 877 | if (lo == NULL) { | ||
| 878 | spin_unlock(&inode->i_lock); | ||
| 879 | return 0; | ||
| 880 | } | ||
| 881 | pnfs_get_layout_hdr(lo); | ||
| 882 | /* Block new layoutgets and read/write to ds */ | ||
| 883 | lo->plh_block_lgets++; | ||
| 884 | spin_unlock(&inode->i_lock); | ||
| 885 | filemap_fdatawait(inode->i_mapping); | ||
| 886 | ret = pnfs_layoutcommit_inode(inode, true); | ||
| 887 | if (ret == 0) | ||
| 888 | ret = _pnfs_return_layout(inode); | ||
| 889 | spin_lock(&inode->i_lock); | ||
| 890 | lo->plh_block_lgets--; | ||
| 891 | spin_unlock(&inode->i_lock); | ||
| 892 | pnfs_put_layout_hdr(lo); | ||
| 893 | return ret; | ||
| 894 | } | ||
| 895 | |||
| 848 | bool pnfs_roc(struct inode *ino) | 896 | bool pnfs_roc(struct inode *ino) |
| 849 | { | 897 | { |
| 850 | struct pnfs_layout_hdr *lo; | 898 | struct pnfs_layout_hdr *lo; |
| @@ -1458,7 +1506,6 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data) | |||
| 1458 | dprintk("pnfs write error = %d\n", hdr->pnfs_error); | 1506 | dprintk("pnfs write error = %d\n", hdr->pnfs_error); |
| 1459 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & | 1507 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & |
| 1460 | PNFS_LAYOUTRET_ON_ERROR) { | 1508 | PNFS_LAYOUTRET_ON_ERROR) { |
| 1461 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags); | ||
| 1462 | pnfs_return_layout(hdr->inode); | 1509 | pnfs_return_layout(hdr->inode); |
| 1463 | } | 1510 | } |
| 1464 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) | 1511 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) |
| @@ -1613,7 +1660,6 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | |||
| 1613 | dprintk("pnfs read error = %d\n", hdr->pnfs_error); | 1660 | dprintk("pnfs read error = %d\n", hdr->pnfs_error); |
| 1614 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & | 1661 | if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags & |
| 1615 | PNFS_LAYOUTRET_ON_ERROR) { | 1662 | PNFS_LAYOUTRET_ON_ERROR) { |
| 1616 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags); | ||
| 1617 | pnfs_return_layout(hdr->inode); | 1663 | pnfs_return_layout(hdr->inode); |
| 1618 | } | 1664 | } |
| 1619 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) | 1665 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) |
| @@ -1746,11 +1792,27 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp) | |||
| 1746 | 1792 | ||
| 1747 | list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) { | 1793 | list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) { |
| 1748 | if (lseg->pls_range.iomode == IOMODE_RW && | 1794 | if (lseg->pls_range.iomode == IOMODE_RW && |
| 1749 | test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) | 1795 | test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) |
| 1750 | list_add(&lseg->pls_lc_list, listp); | 1796 | list_add(&lseg->pls_lc_list, listp); |
| 1751 | } | 1797 | } |
| 1752 | } | 1798 | } |
| 1753 | 1799 | ||
| 1800 | static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp) | ||
| 1801 | { | ||
| 1802 | struct pnfs_layout_segment *lseg, *tmp; | ||
| 1803 | unsigned long *bitlock = &NFS_I(inode)->flags; | ||
| 1804 | |||
| 1805 | /* Matched by references in pnfs_set_layoutcommit */ | ||
| 1806 | list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) { | ||
| 1807 | list_del_init(&lseg->pls_lc_list); | ||
| 1808 | pnfs_put_lseg(lseg); | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); | ||
| 1812 | smp_mb__after_clear_bit(); | ||
| 1813 | wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING); | ||
| 1814 | } | ||
| 1815 | |||
| 1754 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) | 1816 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) |
| 1755 | { | 1817 | { |
| 1756 | pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode); | 1818 | pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode); |
| @@ -1795,6 +1857,7 @@ void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data) | |||
| 1795 | 1857 | ||
| 1796 | if (nfss->pnfs_curr_ld->cleanup_layoutcommit) | 1858 | if (nfss->pnfs_curr_ld->cleanup_layoutcommit) |
| 1797 | nfss->pnfs_curr_ld->cleanup_layoutcommit(data); | 1859 | nfss->pnfs_curr_ld->cleanup_layoutcommit(data); |
| 1860 | pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list); | ||
| 1798 | } | 1861 | } |
| 1799 | 1862 | ||
| 1800 | /* | 1863 | /* |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 94ba80417748..f5f8a470a647 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -219,6 +219,7 @@ void pnfs_set_layoutcommit(struct nfs_write_data *wdata); | |||
| 219 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); | 219 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); |
| 220 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); | 220 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); |
| 221 | int _pnfs_return_layout(struct inode *); | 221 | int _pnfs_return_layout(struct inode *); |
| 222 | int pnfs_commit_and_return_layout(struct inode *); | ||
| 222 | void pnfs_ld_write_done(struct nfs_write_data *); | 223 | void pnfs_ld_write_done(struct nfs_write_data *); |
| 223 | void pnfs_ld_read_done(struct nfs_read_data *); | 224 | void pnfs_ld_read_done(struct nfs_read_data *); |
| 224 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, | 225 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, |
| @@ -407,6 +408,11 @@ static inline int pnfs_return_layout(struct inode *ino) | |||
| 407 | return 0; | 408 | return 0; |
| 408 | } | 409 | } |
| 409 | 410 | ||
| 411 | static inline int pnfs_commit_and_return_layout(struct inode *inode) | ||
| 412 | { | ||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 410 | static inline bool | 416 | static inline bool |
| 411 | pnfs_ld_layoutret_on_setattr(struct inode *inode) | 417 | pnfs_ld_layoutret_on_setattr(struct inode *inode) |
| 412 | { | 418 | { |
