diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 336 |
1 files changed, 214 insertions, 122 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e7f8d5ff2581..2e7c9f7a6f7c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -495,12 +495,11 @@ static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | |||
| 495 | args->sa_privileged = 1; | 495 | args->sa_privileged = 1; |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | static int nfs40_setup_sequence(const struct nfs_server *server, | 498 | int nfs40_setup_sequence(struct nfs4_slot_table *tbl, |
| 499 | struct nfs4_sequence_args *args, | 499 | struct nfs4_sequence_args *args, |
| 500 | struct nfs4_sequence_res *res, | 500 | struct nfs4_sequence_res *res, |
| 501 | struct rpc_task *task) | 501 | struct rpc_task *task) |
| 502 | { | 502 | { |
| 503 | struct nfs4_slot_table *tbl = server->nfs_client->cl_slot_tbl; | ||
| 504 | struct nfs4_slot *slot; | 503 | struct nfs4_slot *slot; |
| 505 | 504 | ||
| 506 | /* slot already allocated? */ | 505 | /* slot already allocated? */ |
| @@ -535,6 +534,7 @@ out_sleep: | |||
| 535 | spin_unlock(&tbl->slot_tbl_lock); | 534 | spin_unlock(&tbl->slot_tbl_lock); |
| 536 | return -EAGAIN; | 535 | return -EAGAIN; |
| 537 | } | 536 | } |
| 537 | EXPORT_SYMBOL_GPL(nfs40_setup_sequence); | ||
| 538 | 538 | ||
| 539 | static int nfs40_sequence_done(struct rpc_task *task, | 539 | static int nfs40_sequence_done(struct rpc_task *task, |
| 540 | struct nfs4_sequence_res *res) | 540 | struct nfs4_sequence_res *res) |
| @@ -694,8 +694,7 @@ out_retry: | |||
| 694 | } | 694 | } |
| 695 | EXPORT_SYMBOL_GPL(nfs41_sequence_done); | 695 | EXPORT_SYMBOL_GPL(nfs41_sequence_done); |
| 696 | 696 | ||
| 697 | static int nfs4_sequence_done(struct rpc_task *task, | 697 | int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
| 698 | struct nfs4_sequence_res *res) | ||
| 699 | { | 698 | { |
| 700 | if (res->sr_slot == NULL) | 699 | if (res->sr_slot == NULL) |
| 701 | return 1; | 700 | return 1; |
| @@ -703,6 +702,7 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
| 703 | return nfs40_sequence_done(task, res); | 702 | return nfs40_sequence_done(task, res); |
| 704 | return nfs41_sequence_done(task, res); | 703 | return nfs41_sequence_done(task, res); |
| 705 | } | 704 | } |
| 705 | EXPORT_SYMBOL_GPL(nfs4_sequence_done); | ||
| 706 | 706 | ||
| 707 | int nfs41_setup_sequence(struct nfs4_session *session, | 707 | int nfs41_setup_sequence(struct nfs4_session *session, |
| 708 | struct nfs4_sequence_args *args, | 708 | struct nfs4_sequence_args *args, |
| @@ -777,7 +777,8 @@ static int nfs4_setup_sequence(const struct nfs_server *server, | |||
| 777 | int ret = 0; | 777 | int ret = 0; |
| 778 | 778 | ||
| 779 | if (!session) | 779 | if (!session) |
| 780 | return nfs40_setup_sequence(server, args, res, task); | 780 | return nfs40_setup_sequence(server->nfs_client->cl_slot_tbl, |
| 781 | args, res, task); | ||
| 781 | 782 | ||
| 782 | dprintk("--> %s clp %p session %p sr_slot %u\n", | 783 | dprintk("--> %s clp %p session %p sr_slot %u\n", |
| 783 | __func__, session->clp, session, res->sr_slot ? | 784 | __func__, session->clp, session, res->sr_slot ? |
| @@ -818,14 +819,16 @@ static int nfs4_setup_sequence(const struct nfs_server *server, | |||
| 818 | struct nfs4_sequence_res *res, | 819 | struct nfs4_sequence_res *res, |
| 819 | struct rpc_task *task) | 820 | struct rpc_task *task) |
| 820 | { | 821 | { |
| 821 | return nfs40_setup_sequence(server, args, res, task); | 822 | return nfs40_setup_sequence(server->nfs_client->cl_slot_tbl, |
| 823 | args, res, task); | ||
| 822 | } | 824 | } |
| 823 | 825 | ||
| 824 | static int nfs4_sequence_done(struct rpc_task *task, | 826 | int nfs4_sequence_done(struct rpc_task *task, |
| 825 | struct nfs4_sequence_res *res) | 827 | struct nfs4_sequence_res *res) |
| 826 | { | 828 | { |
| 827 | return nfs40_sequence_done(task, res); | 829 | return nfs40_sequence_done(task, res); |
| 828 | } | 830 | } |
| 831 | EXPORT_SYMBOL_GPL(nfs4_sequence_done); | ||
| 829 | 832 | ||
| 830 | #endif /* !CONFIG_NFS_V4_1 */ | 833 | #endif /* !CONFIG_NFS_V4_1 */ |
| 831 | 834 | ||
| @@ -937,6 +940,31 @@ static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, | |||
| 937 | return true; | 940 | return true; |
| 938 | } | 941 | } |
| 939 | 942 | ||
| 943 | static u32 | ||
| 944 | nfs4_map_atomic_open_share(struct nfs_server *server, | ||
| 945 | fmode_t fmode, int openflags) | ||
| 946 | { | ||
| 947 | u32 res = 0; | ||
| 948 | |||
| 949 | switch (fmode & (FMODE_READ | FMODE_WRITE)) { | ||
| 950 | case FMODE_READ: | ||
| 951 | res = NFS4_SHARE_ACCESS_READ; | ||
| 952 | break; | ||
| 953 | case FMODE_WRITE: | ||
| 954 | res = NFS4_SHARE_ACCESS_WRITE; | ||
| 955 | break; | ||
| 956 | case FMODE_READ|FMODE_WRITE: | ||
| 957 | res = NFS4_SHARE_ACCESS_BOTH; | ||
| 958 | } | ||
| 959 | if (!(server->caps & NFS_CAP_ATOMIC_OPEN_V1)) | ||
| 960 | goto out; | ||
| 961 | /* Want no delegation if we're using O_DIRECT */ | ||
| 962 | if (openflags & O_DIRECT) | ||
| 963 | res |= NFS4_SHARE_WANT_NO_DELEG; | ||
| 964 | out: | ||
| 965 | return res; | ||
| 966 | } | ||
| 967 | |||
| 940 | static enum open_claim_type4 | 968 | static enum open_claim_type4 |
| 941 | nfs4_map_atomic_open_claim(struct nfs_server *server, | 969 | nfs4_map_atomic_open_claim(struct nfs_server *server, |
| 942 | enum open_claim_type4 claim) | 970 | enum open_claim_type4 claim) |
| @@ -977,6 +1005,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 977 | struct dentry *parent = dget_parent(dentry); | 1005 | struct dentry *parent = dget_parent(dentry); |
| 978 | struct inode *dir = parent->d_inode; | 1006 | struct inode *dir = parent->d_inode; |
| 979 | struct nfs_server *server = NFS_SERVER(dir); | 1007 | struct nfs_server *server = NFS_SERVER(dir); |
| 1008 | struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); | ||
| 980 | struct nfs4_opendata *p; | 1009 | struct nfs4_opendata *p; |
| 981 | 1010 | ||
| 982 | p = kzalloc(sizeof(*p), gfp_mask); | 1011 | p = kzalloc(sizeof(*p), gfp_mask); |
| @@ -987,8 +1016,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 987 | if (IS_ERR(p->f_label)) | 1016 | if (IS_ERR(p->f_label)) |
| 988 | goto err_free_p; | 1017 | goto err_free_p; |
| 989 | 1018 | ||
| 990 | p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask); | 1019 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; |
| 991 | if (p->o_arg.seqid == NULL) | 1020 | p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask); |
| 1021 | if (IS_ERR(p->o_arg.seqid)) | ||
| 992 | goto err_free_label; | 1022 | goto err_free_label; |
| 993 | nfs_sb_active(dentry->d_sb); | 1023 | nfs_sb_active(dentry->d_sb); |
| 994 | p->dentry = dget(dentry); | 1024 | p->dentry = dget(dentry); |
| @@ -997,6 +1027,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
| 997 | atomic_inc(&sp->so_count); | 1027 | atomic_inc(&sp->so_count); |
| 998 | p->o_arg.open_flags = flags; | 1028 | p->o_arg.open_flags = flags; |
| 999 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); | 1029 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); |
| 1030 | p->o_arg.share_access = nfs4_map_atomic_open_share(server, | ||
| 1031 | fmode, flags); | ||
| 1000 | /* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS | 1032 | /* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS |
| 1001 | * will return permission denied for all bits until close */ | 1033 | * will return permission denied for all bits until close */ |
| 1002 | if (!(flags & O_EXCL)) { | 1034 | if (!(flags & O_EXCL)) { |
| @@ -1117,8 +1149,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode) | |||
| 1117 | return 0; | 1149 | return 0; |
| 1118 | if ((delegation->type & fmode) != fmode) | 1150 | if ((delegation->type & fmode) != fmode) |
| 1119 | return 0; | 1151 | return 0; |
| 1120 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) | ||
| 1121 | return 0; | ||
| 1122 | if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) | 1152 | if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) |
| 1123 | return 0; | 1153 | return 0; |
| 1124 | nfs_mark_delegation_referenced(delegation); | 1154 | nfs_mark_delegation_referenced(delegation); |
| @@ -1169,6 +1199,16 @@ static bool nfs_need_update_open_stateid(struct nfs4_state *state, | |||
| 1169 | return false; | 1199 | return false; |
| 1170 | } | 1200 | } |
| 1171 | 1201 | ||
| 1202 | static void nfs_resync_open_stateid_locked(struct nfs4_state *state) | ||
| 1203 | { | ||
| 1204 | if (state->n_wronly) | ||
| 1205 | set_bit(NFS_O_WRONLY_STATE, &state->flags); | ||
| 1206 | if (state->n_rdonly) | ||
| 1207 | set_bit(NFS_O_RDONLY_STATE, &state->flags); | ||
| 1208 | if (state->n_rdwr) | ||
| 1209 | set_bit(NFS_O_RDWR_STATE, &state->flags); | ||
| 1210 | } | ||
| 1211 | |||
| 1172 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, | 1212 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, |
| 1173 | nfs4_stateid *stateid, fmode_t fmode) | 1213 | nfs4_stateid *stateid, fmode_t fmode) |
| 1174 | { | 1214 | { |
| @@ -1187,8 +1227,12 @@ static void nfs_clear_open_stateid_locked(struct nfs4_state *state, | |||
| 1187 | } | 1227 | } |
| 1188 | if (stateid == NULL) | 1228 | if (stateid == NULL) |
| 1189 | return; | 1229 | return; |
| 1190 | if (!nfs_need_update_open_stateid(state, stateid)) | 1230 | /* Handle races with OPEN */ |
| 1231 | if (!nfs4_stateid_match_other(stateid, &state->open_stateid) || | ||
| 1232 | !nfs4_stateid_is_newer(stateid, &state->open_stateid)) { | ||
| 1233 | nfs_resync_open_stateid_locked(state); | ||
| 1191 | return; | 1234 | return; |
| 1235 | } | ||
| 1192 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | 1236 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) |
| 1193 | nfs4_stateid_copy(&state->stateid, stateid); | 1237 | nfs4_stateid_copy(&state->stateid, stateid); |
| 1194 | nfs4_stateid_copy(&state->open_stateid, stateid); | 1238 | nfs4_stateid_copy(&state->open_stateid, stateid); |
| @@ -1283,6 +1327,23 @@ no_delegation: | |||
| 1283 | return ret; | 1327 | return ret; |
| 1284 | } | 1328 | } |
| 1285 | 1329 | ||
| 1330 | static bool nfs4_update_lock_stateid(struct nfs4_lock_state *lsp, | ||
| 1331 | const nfs4_stateid *stateid) | ||
| 1332 | { | ||
| 1333 | struct nfs4_state *state = lsp->ls_state; | ||
| 1334 | bool ret = false; | ||
| 1335 | |||
| 1336 | spin_lock(&state->state_lock); | ||
| 1337 | if (!nfs4_stateid_match_other(stateid, &lsp->ls_stateid)) | ||
| 1338 | goto out_noupdate; | ||
| 1339 | if (!nfs4_stateid_is_newer(stateid, &lsp->ls_stateid)) | ||
| 1340 | goto out_noupdate; | ||
| 1341 | nfs4_stateid_copy(&lsp->ls_stateid, stateid); | ||
| 1342 | ret = true; | ||
| 1343 | out_noupdate: | ||
| 1344 | spin_unlock(&state->state_lock); | ||
| 1345 | return ret; | ||
| 1346 | } | ||
| 1286 | 1347 | ||
| 1287 | static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode) | 1348 | static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode) |
| 1288 | { | 1349 | { |
| @@ -1681,8 +1742,8 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | |||
| 1681 | { | 1742 | { |
| 1682 | struct nfs4_opendata *data = calldata; | 1743 | struct nfs4_opendata *data = calldata; |
| 1683 | 1744 | ||
| 1684 | nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args, | 1745 | nfs40_setup_sequence(data->o_arg.server->nfs_client->cl_slot_tbl, |
| 1685 | &data->c_res.seq_res, task); | 1746 | &data->c_arg.seq_args, &data->c_res.seq_res, task); |
| 1686 | } | 1747 | } |
| 1687 | 1748 | ||
| 1688 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1749 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
| @@ -2589,6 +2650,11 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
| 2589 | case -NFS4ERR_OLD_STATEID: | 2650 | case -NFS4ERR_OLD_STATEID: |
| 2590 | case -NFS4ERR_BAD_STATEID: | 2651 | case -NFS4ERR_BAD_STATEID: |
| 2591 | case -NFS4ERR_EXPIRED: | 2652 | case -NFS4ERR_EXPIRED: |
| 2653 | if (!nfs4_stateid_match(&calldata->arg.stateid, | ||
| 2654 | &state->stateid)) { | ||
| 2655 | rpc_restart_call_prepare(task); | ||
| 2656 | goto out_release; | ||
| 2657 | } | ||
| 2592 | if (calldata->arg.fmode == 0) | 2658 | if (calldata->arg.fmode == 0) |
| 2593 | break; | 2659 | break; |
| 2594 | default: | 2660 | default: |
| @@ -2621,6 +2687,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
| 2621 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2687 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
| 2622 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2688 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
| 2623 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2689 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); |
| 2690 | nfs4_stateid_copy(&calldata->arg.stateid, &state->stateid); | ||
| 2624 | /* Calculate the change in open mode */ | 2691 | /* Calculate the change in open mode */ |
| 2625 | calldata->arg.fmode = 0; | 2692 | calldata->arg.fmode = 0; |
| 2626 | if (state->n_rdwr == 0) { | 2693 | if (state->n_rdwr == 0) { |
| @@ -2655,6 +2722,9 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
| 2655 | goto out_wait; | 2722 | goto out_wait; |
| 2656 | } | 2723 | } |
| 2657 | } | 2724 | } |
| 2725 | calldata->arg.share_access = | ||
| 2726 | nfs4_map_atomic_open_share(NFS_SERVER(inode), | ||
| 2727 | calldata->arg.fmode, 0); | ||
| 2658 | 2728 | ||
| 2659 | nfs_fattr_init(calldata->res.fattr); | 2729 | nfs_fattr_init(calldata->res.fattr); |
| 2660 | calldata->timestamp = jiffies; | 2730 | calldata->timestamp = jiffies; |
| @@ -2677,45 +2747,10 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
| 2677 | .rpc_release = nfs4_free_closedata, | 2747 | .rpc_release = nfs4_free_closedata, |
| 2678 | }; | 2748 | }; |
| 2679 | 2749 | ||
| 2680 | static bool nfs4_state_has_opener(struct nfs4_state *state) | ||
| 2681 | { | ||
| 2682 | /* first check existing openers */ | ||
| 2683 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0 && | ||
| 2684 | state->n_rdonly != 0) | ||
| 2685 | return true; | ||
| 2686 | |||
| 2687 | if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0 && | ||
| 2688 | state->n_wronly != 0) | ||
| 2689 | return true; | ||
| 2690 | |||
| 2691 | if (test_bit(NFS_O_RDWR_STATE, &state->flags) != 0 && | ||
| 2692 | state->n_rdwr != 0) | ||
| 2693 | return true; | ||
| 2694 | |||
| 2695 | return false; | ||
| 2696 | } | ||
| 2697 | |||
| 2698 | static bool nfs4_roc(struct inode *inode) | 2750 | static bool nfs4_roc(struct inode *inode) |
| 2699 | { | 2751 | { |
| 2700 | struct nfs_inode *nfsi = NFS_I(inode); | 2752 | if (!nfs_have_layout(inode)) |
| 2701 | struct nfs_open_context *ctx; | ||
| 2702 | struct nfs4_state *state; | ||
| 2703 | |||
| 2704 | spin_lock(&inode->i_lock); | ||
| 2705 | list_for_each_entry(ctx, &nfsi->open_files, list) { | ||
| 2706 | state = ctx->state; | ||
| 2707 | if (state == NULL) | ||
| 2708 | continue; | ||
| 2709 | if (nfs4_state_has_opener(state)) { | ||
| 2710 | spin_unlock(&inode->i_lock); | ||
| 2711 | return false; | ||
| 2712 | } | ||
| 2713 | } | ||
| 2714 | spin_unlock(&inode->i_lock); | ||
| 2715 | |||
| 2716 | if (nfs4_check_delegation(inode, FMODE_READ)) | ||
| 2717 | return false; | 2753 | return false; |
| 2718 | |||
| 2719 | return pnfs_roc(inode); | 2754 | return pnfs_roc(inode); |
| 2720 | } | 2755 | } |
| 2721 | 2756 | ||
| @@ -2733,6 +2768,7 @@ static bool nfs4_roc(struct inode *inode) | |||
| 2733 | int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) | 2768 | int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) |
| 2734 | { | 2769 | { |
| 2735 | struct nfs_server *server = NFS_SERVER(state->inode); | 2770 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 2771 | struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); | ||
| 2736 | struct nfs4_closedata *calldata; | 2772 | struct nfs4_closedata *calldata; |
| 2737 | struct nfs4_state_owner *sp = state->owner; | 2773 | struct nfs4_state_owner *sp = state->owner; |
| 2738 | struct rpc_task *task; | 2774 | struct rpc_task *task; |
| @@ -2759,10 +2795,10 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) | |||
| 2759 | calldata->inode = state->inode; | 2795 | calldata->inode = state->inode; |
| 2760 | calldata->state = state; | 2796 | calldata->state = state; |
| 2761 | calldata->arg.fh = NFS_FH(state->inode); | 2797 | calldata->arg.fh = NFS_FH(state->inode); |
| 2762 | calldata->arg.stateid = &state->open_stateid; | ||
| 2763 | /* Serialization for the sequence id */ | 2798 | /* Serialization for the sequence id */ |
| 2764 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid, gfp_mask); | 2799 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; |
| 2765 | if (calldata->arg.seqid == NULL) | 2800 | calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask); |
| 2801 | if (IS_ERR(calldata->arg.seqid)) | ||
| 2766 | goto out_free_calldata; | 2802 | goto out_free_calldata; |
| 2767 | calldata->arg.fmode = 0; | 2803 | calldata->arg.fmode = 0; |
| 2768 | calldata->arg.bitmask = server->cache_consistency_bitmask; | 2804 | calldata->arg.bitmask = server->cache_consistency_bitmask; |
| @@ -4917,11 +4953,14 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, | |||
| 4917 | } | 4953 | } |
| 4918 | 4954 | ||
| 4919 | static unsigned int | 4955 | static unsigned int |
| 4920 | nfs4_init_nonuniform_client_string(const struct nfs_client *clp, | 4956 | nfs4_init_nonuniform_client_string(struct nfs_client *clp, |
| 4921 | char *buf, size_t len) | 4957 | char *buf, size_t len) |
| 4922 | { | 4958 | { |
| 4923 | unsigned int result; | 4959 | unsigned int result; |
| 4924 | 4960 | ||
| 4961 | if (clp->cl_owner_id != NULL) | ||
| 4962 | return strlcpy(buf, clp->cl_owner_id, len); | ||
| 4963 | |||
| 4925 | rcu_read_lock(); | 4964 | rcu_read_lock(); |
| 4926 | result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s", | 4965 | result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s", |
| 4927 | clp->cl_ipaddr, | 4966 | clp->cl_ipaddr, |
| @@ -4930,24 +4969,32 @@ nfs4_init_nonuniform_client_string(const struct nfs_client *clp, | |||
| 4930 | rpc_peeraddr2str(clp->cl_rpcclient, | 4969 | rpc_peeraddr2str(clp->cl_rpcclient, |
| 4931 | RPC_DISPLAY_PROTO)); | 4970 | RPC_DISPLAY_PROTO)); |
| 4932 | rcu_read_unlock(); | 4971 | rcu_read_unlock(); |
| 4972 | clp->cl_owner_id = kstrdup(buf, GFP_KERNEL); | ||
| 4933 | return result; | 4973 | return result; |
| 4934 | } | 4974 | } |
| 4935 | 4975 | ||
| 4936 | static unsigned int | 4976 | static unsigned int |
| 4937 | nfs4_init_uniform_client_string(const struct nfs_client *clp, | 4977 | nfs4_init_uniform_client_string(struct nfs_client *clp, |
| 4938 | char *buf, size_t len) | 4978 | char *buf, size_t len) |
| 4939 | { | 4979 | { |
| 4940 | const char *nodename = clp->cl_rpcclient->cl_nodename; | 4980 | const char *nodename = clp->cl_rpcclient->cl_nodename; |
| 4981 | unsigned int result; | ||
| 4982 | |||
| 4983 | if (clp->cl_owner_id != NULL) | ||
| 4984 | return strlcpy(buf, clp->cl_owner_id, len); | ||
| 4941 | 4985 | ||
| 4942 | if (nfs4_client_id_uniquifier[0] != '\0') | 4986 | if (nfs4_client_id_uniquifier[0] != '\0') |
| 4943 | return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s", | 4987 | result = scnprintf(buf, len, "Linux NFSv%u.%u %s/%s", |
| 4944 | clp->rpc_ops->version, | 4988 | clp->rpc_ops->version, |
| 4945 | clp->cl_minorversion, | 4989 | clp->cl_minorversion, |
| 4946 | nfs4_client_id_uniquifier, | 4990 | nfs4_client_id_uniquifier, |
| 4947 | nodename); | 4991 | nodename); |
| 4948 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", | 4992 | else |
| 4993 | result = scnprintf(buf, len, "Linux NFSv%u.%u %s", | ||
| 4949 | clp->rpc_ops->version, clp->cl_minorversion, | 4994 | clp->rpc_ops->version, clp->cl_minorversion, |
| 4950 | nodename); | 4995 | nodename); |
| 4996 | clp->cl_owner_id = kstrdup(buf, GFP_KERNEL); | ||
| 4997 | return result; | ||
| 4951 | } | 4998 | } |
| 4952 | 4999 | ||
| 4953 | /* | 5000 | /* |
| @@ -5128,9 +5175,13 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
| 5128 | static void nfs4_delegreturn_release(void *calldata) | 5175 | static void nfs4_delegreturn_release(void *calldata) |
| 5129 | { | 5176 | { |
| 5130 | struct nfs4_delegreturndata *data = calldata; | 5177 | struct nfs4_delegreturndata *data = calldata; |
| 5178 | struct inode *inode = data->inode; | ||
| 5131 | 5179 | ||
| 5132 | if (data->roc) | 5180 | if (inode) { |
| 5133 | pnfs_roc_release(data->inode); | 5181 | if (data->roc) |
| 5182 | pnfs_roc_release(inode); | ||
| 5183 | nfs_iput_and_deactive(inode); | ||
| 5184 | } | ||
| 5134 | kfree(calldata); | 5185 | kfree(calldata); |
| 5135 | } | 5186 | } |
| 5136 | 5187 | ||
| @@ -5187,9 +5238,9 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
| 5187 | nfs_fattr_init(data->res.fattr); | 5238 | nfs_fattr_init(data->res.fattr); |
| 5188 | data->timestamp = jiffies; | 5239 | data->timestamp = jiffies; |
| 5189 | data->rpc_status = 0; | 5240 | data->rpc_status = 0; |
| 5190 | data->inode = inode; | 5241 | data->inode = nfs_igrab_and_active(inode); |
| 5191 | data->roc = list_empty(&NFS_I(inode)->open_files) ? | 5242 | if (data->inode) |
| 5192 | pnfs_roc(inode) : false; | 5243 | data->roc = nfs4_roc(inode); |
| 5193 | 5244 | ||
| 5194 | task_setup_data.callback_data = data; | 5245 | task_setup_data.callback_data = data; |
| 5195 | msg.rpc_argp = &data->args; | 5246 | msg.rpc_argp = &data->args; |
| @@ -5344,7 +5395,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | |||
| 5344 | p->arg.fl = &p->fl; | 5395 | p->arg.fl = &p->fl; |
| 5345 | p->arg.seqid = seqid; | 5396 | p->arg.seqid = seqid; |
| 5346 | p->res.seqid = seqid; | 5397 | p->res.seqid = seqid; |
| 5347 | p->arg.stateid = &lsp->ls_stateid; | ||
| 5348 | p->lsp = lsp; | 5398 | p->lsp = lsp; |
| 5349 | atomic_inc(&lsp->ls_count); | 5399 | atomic_inc(&lsp->ls_count); |
| 5350 | /* Ensure we don't close file until we're done freeing locks! */ | 5400 | /* Ensure we don't close file until we're done freeing locks! */ |
| @@ -5371,14 +5421,18 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
| 5371 | return; | 5421 | return; |
| 5372 | switch (task->tk_status) { | 5422 | switch (task->tk_status) { |
| 5373 | case 0: | 5423 | case 0: |
| 5374 | nfs4_stateid_copy(&calldata->lsp->ls_stateid, | ||
| 5375 | &calldata->res.stateid); | ||
| 5376 | renew_lease(calldata->server, calldata->timestamp); | 5424 | renew_lease(calldata->server, calldata->timestamp); |
| 5377 | break; | 5425 | do_vfs_lock(calldata->fl.fl_file, &calldata->fl); |
| 5426 | if (nfs4_update_lock_stateid(calldata->lsp, | ||
| 5427 | &calldata->res.stateid)) | ||
| 5428 | break; | ||
| 5378 | case -NFS4ERR_BAD_STATEID: | 5429 | case -NFS4ERR_BAD_STATEID: |
| 5379 | case -NFS4ERR_OLD_STATEID: | 5430 | case -NFS4ERR_OLD_STATEID: |
| 5380 | case -NFS4ERR_STALE_STATEID: | 5431 | case -NFS4ERR_STALE_STATEID: |
| 5381 | case -NFS4ERR_EXPIRED: | 5432 | case -NFS4ERR_EXPIRED: |
| 5433 | if (!nfs4_stateid_match(&calldata->arg.stateid, | ||
| 5434 | &calldata->lsp->ls_stateid)) | ||
| 5435 | rpc_restart_call_prepare(task); | ||
| 5382 | break; | 5436 | break; |
| 5383 | default: | 5437 | default: |
| 5384 | if (nfs4_async_handle_error(task, calldata->server, | 5438 | if (nfs4_async_handle_error(task, calldata->server, |
| @@ -5394,6 +5448,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
| 5394 | 5448 | ||
| 5395 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 5449 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
| 5396 | goto out_wait; | 5450 | goto out_wait; |
| 5451 | nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid); | ||
| 5397 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { | 5452 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { |
| 5398 | /* Note: exit _without_ running nfs4_locku_done */ | 5453 | /* Note: exit _without_ running nfs4_locku_done */ |
| 5399 | goto out_no_action; | 5454 | goto out_no_action; |
| @@ -5464,6 +5519,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
| 5464 | struct nfs_seqid *seqid; | 5519 | struct nfs_seqid *seqid; |
| 5465 | struct nfs4_lock_state *lsp; | 5520 | struct nfs4_lock_state *lsp; |
| 5466 | struct rpc_task *task; | 5521 | struct rpc_task *task; |
| 5522 | struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); | ||
| 5467 | int status = 0; | 5523 | int status = 0; |
| 5468 | unsigned char fl_flags = request->fl_flags; | 5524 | unsigned char fl_flags = request->fl_flags; |
| 5469 | 5525 | ||
| @@ -5487,9 +5543,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
| 5487 | lsp = request->fl_u.nfs4_fl.owner; | 5543 | lsp = request->fl_u.nfs4_fl.owner; |
| 5488 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0) | 5544 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0) |
| 5489 | goto out; | 5545 | goto out; |
| 5490 | seqid = nfs_alloc_seqid(&lsp->ls_seqid, GFP_KERNEL); | 5546 | alloc_seqid = NFS_SERVER(inode)->nfs_client->cl_mvops->alloc_seqid; |
| 5547 | seqid = alloc_seqid(&lsp->ls_seqid, GFP_KERNEL); | ||
| 5491 | status = -ENOMEM; | 5548 | status = -ENOMEM; |
| 5492 | if (seqid == NULL) | 5549 | if (IS_ERR(seqid)) |
| 5493 | goto out; | 5550 | goto out; |
| 5494 | task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid); | 5551 | task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid); |
| 5495 | status = PTR_ERR(task); | 5552 | status = PTR_ERR(task); |
| @@ -5522,6 +5579,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
| 5522 | struct nfs4_lockdata *p; | 5579 | struct nfs4_lockdata *p; |
| 5523 | struct inode *inode = lsp->ls_state->inode; | 5580 | struct inode *inode = lsp->ls_state->inode; |
| 5524 | struct nfs_server *server = NFS_SERVER(inode); | 5581 | struct nfs_server *server = NFS_SERVER(inode); |
| 5582 | struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); | ||
| 5525 | 5583 | ||
| 5526 | p = kzalloc(sizeof(*p), gfp_mask); | 5584 | p = kzalloc(sizeof(*p), gfp_mask); |
| 5527 | if (p == NULL) | 5585 | if (p == NULL) |
| @@ -5530,12 +5588,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
| 5530 | p->arg.fh = NFS_FH(inode); | 5588 | p->arg.fh = NFS_FH(inode); |
| 5531 | p->arg.fl = &p->fl; | 5589 | p->arg.fl = &p->fl; |
| 5532 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask); | 5590 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask); |
| 5533 | if (p->arg.open_seqid == NULL) | 5591 | if (IS_ERR(p->arg.open_seqid)) |
| 5534 | goto out_free; | 5592 | goto out_free; |
| 5535 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid, gfp_mask); | 5593 | alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid; |
| 5536 | if (p->arg.lock_seqid == NULL) | 5594 | p->arg.lock_seqid = alloc_seqid(&lsp->ls_seqid, gfp_mask); |
| 5595 | if (IS_ERR(p->arg.lock_seqid)) | ||
| 5537 | goto out_free_seqid; | 5596 | goto out_free_seqid; |
| 5538 | p->arg.lock_stateid = &lsp->ls_stateid; | ||
| 5539 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 5597 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
| 5540 | p->arg.lock_owner.id = lsp->ls_seqid.owner_id; | 5598 | p->arg.lock_owner.id = lsp->ls_seqid.owner_id; |
| 5541 | p->arg.lock_owner.s_dev = server->s_dev; | 5599 | p->arg.lock_owner.s_dev = server->s_dev; |
| @@ -5562,15 +5620,19 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
| 5562 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) | 5620 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) |
| 5563 | goto out_wait; | 5621 | goto out_wait; |
| 5564 | /* Do we need to do an open_to_lock_owner? */ | 5622 | /* Do we need to do an open_to_lock_owner? */ |
| 5565 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 5623 | if (!test_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags)) { |
| 5566 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) { | 5624 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) { |
| 5567 | goto out_release_lock_seqid; | 5625 | goto out_release_lock_seqid; |
| 5568 | } | 5626 | } |
| 5569 | data->arg.open_stateid = &state->open_stateid; | 5627 | nfs4_stateid_copy(&data->arg.open_stateid, |
| 5628 | &state->open_stateid); | ||
| 5570 | data->arg.new_lock_owner = 1; | 5629 | data->arg.new_lock_owner = 1; |
| 5571 | data->res.open_seqid = data->arg.open_seqid; | 5630 | data->res.open_seqid = data->arg.open_seqid; |
| 5572 | } else | 5631 | } else { |
| 5573 | data->arg.new_lock_owner = 0; | 5632 | data->arg.new_lock_owner = 0; |
| 5633 | nfs4_stateid_copy(&data->arg.lock_stateid, | ||
| 5634 | &data->lsp->ls_stateid); | ||
| 5635 | } | ||
| 5574 | if (!nfs4_valid_open_stateid(state)) { | 5636 | if (!nfs4_valid_open_stateid(state)) { |
| 5575 | data->rpc_status = -EBADF; | 5637 | data->rpc_status = -EBADF; |
| 5576 | task->tk_action = NULL; | 5638 | task->tk_action = NULL; |
| @@ -5594,6 +5656,7 @@ out_wait: | |||
| 5594 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) | 5656 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) |
| 5595 | { | 5657 | { |
| 5596 | struct nfs4_lockdata *data = calldata; | 5658 | struct nfs4_lockdata *data = calldata; |
| 5659 | struct nfs4_lock_state *lsp = data->lsp; | ||
| 5597 | 5660 | ||
| 5598 | dprintk("%s: begin!\n", __func__); | 5661 | dprintk("%s: begin!\n", __func__); |
| 5599 | 5662 | ||
| @@ -5601,18 +5664,36 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
| 5601 | return; | 5664 | return; |
| 5602 | 5665 | ||
| 5603 | data->rpc_status = task->tk_status; | 5666 | data->rpc_status = task->tk_status; |
| 5604 | if (data->arg.new_lock_owner != 0) { | 5667 | switch (task->tk_status) { |
| 5605 | if (data->rpc_status == 0) | 5668 | case 0: |
| 5606 | nfs_confirm_seqid(&data->lsp->ls_seqid, 0); | 5669 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), |
| 5607 | else | 5670 | data->timestamp); |
| 5608 | goto out; | 5671 | if (data->arg.new_lock) { |
| 5609 | } | 5672 | data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS); |
| 5610 | if (data->rpc_status == 0) { | 5673 | if (do_vfs_lock(data->fl.fl_file, &data->fl) < 0) { |
| 5611 | nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid); | 5674 | rpc_restart_call_prepare(task); |
| 5612 | set_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags); | 5675 | break; |
| 5613 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); | 5676 | } |
| 5677 | } | ||
| 5678 | if (data->arg.new_lock_owner != 0) { | ||
| 5679 | nfs_confirm_seqid(&lsp->ls_seqid, 0); | ||
| 5680 | nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid); | ||
| 5681 | set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); | ||
| 5682 | } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid)) | ||
| 5683 | rpc_restart_call_prepare(task); | ||
| 5684 | break; | ||
| 5685 | case -NFS4ERR_BAD_STATEID: | ||
| 5686 | case -NFS4ERR_OLD_STATEID: | ||
| 5687 | case -NFS4ERR_STALE_STATEID: | ||
| 5688 | case -NFS4ERR_EXPIRED: | ||
| 5689 | if (data->arg.new_lock_owner != 0) { | ||
| 5690 | if (!nfs4_stateid_match(&data->arg.open_stateid, | ||
| 5691 | &lsp->ls_state->open_stateid)) | ||
| 5692 | rpc_restart_call_prepare(task); | ||
| 5693 | } else if (!nfs4_stateid_match(&data->arg.lock_stateid, | ||
| 5694 | &lsp->ls_stateid)) | ||
| 5695 | rpc_restart_call_prepare(task); | ||
| 5614 | } | 5696 | } |
| 5615 | out: | ||
| 5616 | dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status); | 5697 | dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status); |
| 5617 | } | 5698 | } |
| 5618 | 5699 | ||
| @@ -5693,7 +5774,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
| 5693 | if (recovery_type == NFS_LOCK_RECLAIM) | 5774 | if (recovery_type == NFS_LOCK_RECLAIM) |
| 5694 | data->arg.reclaim = NFS_LOCK_RECLAIM; | 5775 | data->arg.reclaim = NFS_LOCK_RECLAIM; |
| 5695 | nfs4_set_sequence_privileged(&data->arg.seq_args); | 5776 | nfs4_set_sequence_privileged(&data->arg.seq_args); |
| 5696 | } | 5777 | } else |
| 5778 | data->arg.new_lock = 1; | ||
| 5697 | task = rpc_run_task(&task_setup_data); | 5779 | task = rpc_run_task(&task_setup_data); |
| 5698 | if (IS_ERR(task)) | 5780 | if (IS_ERR(task)) |
| 5699 | return PTR_ERR(task); | 5781 | return PTR_ERR(task); |
| @@ -5817,10 +5899,8 @@ static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *reques | |||
| 5817 | 5899 | ||
| 5818 | static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) | 5900 | static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
| 5819 | { | 5901 | { |
| 5820 | struct nfs4_state_owner *sp = state->owner; | ||
| 5821 | struct nfs_inode *nfsi = NFS_I(state->inode); | 5902 | struct nfs_inode *nfsi = NFS_I(state->inode); |
| 5822 | unsigned char fl_flags = request->fl_flags; | 5903 | unsigned char fl_flags = request->fl_flags; |
| 5823 | unsigned int seq; | ||
| 5824 | int status = -ENOLCK; | 5904 | int status = -ENOLCK; |
| 5825 | 5905 | ||
| 5826 | if ((fl_flags & FL_POSIX) && | 5906 | if ((fl_flags & FL_POSIX) && |
| @@ -5840,25 +5920,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 5840 | /* ...but avoid races with delegation recall... */ | 5920 | /* ...but avoid races with delegation recall... */ |
| 5841 | request->fl_flags = fl_flags & ~FL_SLEEP; | 5921 | request->fl_flags = fl_flags & ~FL_SLEEP; |
| 5842 | status = do_vfs_lock(request->fl_file, request); | 5922 | status = do_vfs_lock(request->fl_file, request); |
| 5843 | goto out_unlock; | 5923 | up_read(&nfsi->rwsem); |
| 5844 | } | ||
| 5845 | seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); | ||
| 5846 | up_read(&nfsi->rwsem); | ||
| 5847 | status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW); | ||
| 5848 | if (status != 0) | ||
| 5849 | goto out; | 5924 | goto out; |
| 5850 | down_read(&nfsi->rwsem); | ||
| 5851 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) { | ||
| 5852 | status = -NFS4ERR_DELAY; | ||
| 5853 | goto out_unlock; | ||
| 5854 | } | 5925 | } |
| 5855 | /* Note: we always want to sleep here! */ | ||
| 5856 | request->fl_flags = fl_flags | FL_SLEEP; | ||
| 5857 | if (do_vfs_lock(request->fl_file, request) < 0) | ||
| 5858 | printk(KERN_WARNING "NFS: %s: VFS is out of sync with lock " | ||
| 5859 | "manager!\n", __func__); | ||
| 5860 | out_unlock: | ||
| 5861 | up_read(&nfsi->rwsem); | 5926 | up_read(&nfsi->rwsem); |
| 5927 | status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW); | ||
| 5862 | out: | 5928 | out: |
| 5863 | request->fl_flags = fl_flags; | 5929 | request->fl_flags = fl_flags; |
| 5864 | return status; | 5930 | return status; |
| @@ -5965,8 +6031,8 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata | |||
| 5965 | { | 6031 | { |
| 5966 | struct nfs_release_lockowner_data *data = calldata; | 6032 | struct nfs_release_lockowner_data *data = calldata; |
| 5967 | struct nfs_server *server = data->server; | 6033 | struct nfs_server *server = data->server; |
| 5968 | nfs40_setup_sequence(server, &data->args.seq_args, | 6034 | nfs40_setup_sequence(server->nfs_client->cl_slot_tbl, |
| 5969 | &data->res.seq_res, task); | 6035 | &data->args.seq_args, &data->res.seq_res, task); |
| 5970 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; | 6036 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
| 5971 | data->timestamp = jiffies; | 6037 | data->timestamp = jiffies; |
| 5972 | } | 6038 | } |
| @@ -7528,6 +7594,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
| 7528 | return; | 7594 | return; |
| 7529 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | 7595 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, |
| 7530 | NFS_I(lgp->args.inode)->layout, | 7596 | NFS_I(lgp->args.inode)->layout, |
| 7597 | &lgp->args.range, | ||
| 7531 | lgp->args.ctx->state)) { | 7598 | lgp->args.ctx->state)) { |
| 7532 | rpc_exit(task, NFS4_OK); | 7599 | rpc_exit(task, NFS4_OK); |
| 7533 | } | 7600 | } |
| @@ -7783,9 +7850,13 @@ static void nfs4_layoutreturn_release(void *calldata) | |||
| 7783 | spin_lock(&lo->plh_inode->i_lock); | 7850 | spin_lock(&lo->plh_inode->i_lock); |
| 7784 | if (lrp->res.lrs_present) | 7851 | if (lrp->res.lrs_present) |
| 7785 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | 7852 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
| 7853 | pnfs_clear_layoutreturn_waitbit(lo); | ||
| 7854 | clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags); | ||
| 7855 | rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); | ||
| 7786 | lo->plh_block_lgets--; | 7856 | lo->plh_block_lgets--; |
| 7787 | spin_unlock(&lo->plh_inode->i_lock); | 7857 | spin_unlock(&lo->plh_inode->i_lock); |
| 7788 | pnfs_put_layout_hdr(lrp->args.layout); | 7858 | pnfs_put_layout_hdr(lrp->args.layout); |
| 7859 | nfs_iput_and_deactive(lrp->inode); | ||
| 7789 | kfree(calldata); | 7860 | kfree(calldata); |
| 7790 | dprintk("<-- %s\n", __func__); | 7861 | dprintk("<-- %s\n", __func__); |
| 7791 | } | 7862 | } |
| @@ -7796,7 +7867,7 @@ static const struct rpc_call_ops nfs4_layoutreturn_call_ops = { | |||
| 7796 | .rpc_release = nfs4_layoutreturn_release, | 7867 | .rpc_release = nfs4_layoutreturn_release, |
| 7797 | }; | 7868 | }; |
| 7798 | 7869 | ||
| 7799 | int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | 7870 | int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync) |
| 7800 | { | 7871 | { |
| 7801 | struct rpc_task *task; | 7872 | struct rpc_task *task; |
| 7802 | struct rpc_message msg = { | 7873 | struct rpc_message msg = { |
| @@ -7811,14 +7882,23 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
| 7811 | .callback_ops = &nfs4_layoutreturn_call_ops, | 7882 | .callback_ops = &nfs4_layoutreturn_call_ops, |
| 7812 | .callback_data = lrp, | 7883 | .callback_data = lrp, |
| 7813 | }; | 7884 | }; |
| 7814 | int status; | 7885 | int status = 0; |
| 7815 | 7886 | ||
| 7816 | dprintk("--> %s\n", __func__); | 7887 | dprintk("--> %s\n", __func__); |
| 7888 | if (!sync) { | ||
| 7889 | lrp->inode = nfs_igrab_and_active(lrp->args.inode); | ||
| 7890 | if (!lrp->inode) { | ||
| 7891 | nfs4_layoutreturn_release(lrp); | ||
| 7892 | return -EAGAIN; | ||
| 7893 | } | ||
| 7894 | task_setup_data.flags |= RPC_TASK_ASYNC; | ||
| 7895 | } | ||
| 7817 | nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); | 7896 | nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1); |
| 7818 | task = rpc_run_task(&task_setup_data); | 7897 | task = rpc_run_task(&task_setup_data); |
| 7819 | if (IS_ERR(task)) | 7898 | if (IS_ERR(task)) |
| 7820 | return PTR_ERR(task); | 7899 | return PTR_ERR(task); |
| 7821 | status = task->tk_status; | 7900 | if (sync) |
| 7901 | status = task->tk_status; | ||
| 7822 | trace_nfs4_layoutreturn(lrp->args.inode, status); | 7902 | trace_nfs4_layoutreturn(lrp->args.inode, status); |
| 7823 | dprintk("<-- %s status=%d\n", __func__, status); | 7903 | dprintk("<-- %s status=%d\n", __func__, status); |
| 7824 | rpc_put_task(task); | 7904 | rpc_put_task(task); |
| @@ -7912,6 +7992,7 @@ static void nfs4_layoutcommit_release(void *calldata) | |||
| 7912 | nfs_post_op_update_inode_force_wcc(data->args.inode, | 7992 | nfs_post_op_update_inode_force_wcc(data->args.inode, |
| 7913 | data->res.fattr); | 7993 | data->res.fattr); |
| 7914 | put_rpccred(data->cred); | 7994 | put_rpccred(data->cred); |
| 7995 | nfs_iput_and_deactive(data->inode); | ||
| 7915 | kfree(data); | 7996 | kfree(data); |
| 7916 | } | 7997 | } |
| 7917 | 7998 | ||
| @@ -7936,7 +8017,6 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
| 7936 | .rpc_message = &msg, | 8017 | .rpc_message = &msg, |
| 7937 | .callback_ops = &nfs4_layoutcommit_ops, | 8018 | .callback_ops = &nfs4_layoutcommit_ops, |
| 7938 | .callback_data = data, | 8019 | .callback_data = data, |
| 7939 | .flags = RPC_TASK_ASYNC, | ||
| 7940 | }; | 8020 | }; |
| 7941 | struct rpc_task *task; | 8021 | struct rpc_task *task; |
| 7942 | int status = 0; | 8022 | int status = 0; |
| @@ -7947,18 +8027,21 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | |||
| 7947 | data->args.lastbytewritten, | 8027 | data->args.lastbytewritten, |
| 7948 | data->args.inode->i_ino); | 8028 | data->args.inode->i_ino); |
| 7949 | 8029 | ||
| 8030 | if (!sync) { | ||
| 8031 | data->inode = nfs_igrab_and_active(data->args.inode); | ||
| 8032 | if (data->inode == NULL) { | ||
| 8033 | nfs4_layoutcommit_release(data); | ||
| 8034 | return -EAGAIN; | ||
| 8035 | } | ||
| 8036 | task_setup_data.flags = RPC_TASK_ASYNC; | ||
| 8037 | } | ||
| 7950 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 8038 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
| 7951 | task = rpc_run_task(&task_setup_data); | 8039 | task = rpc_run_task(&task_setup_data); |
| 7952 | if (IS_ERR(task)) | 8040 | if (IS_ERR(task)) |
| 7953 | return PTR_ERR(task); | 8041 | return PTR_ERR(task); |
| 7954 | if (sync == false) | 8042 | if (sync) |
| 7955 | goto out; | 8043 | status = task->tk_status; |
| 7956 | status = nfs4_wait_for_completion_rpc_task(task); | ||
| 7957 | if (status != 0) | ||
| 7958 | goto out; | ||
| 7959 | status = task->tk_status; | ||
| 7960 | trace_nfs4_layoutcommit(data->args.inode, status); | 8044 | trace_nfs4_layoutcommit(data->args.inode, status); |
| 7961 | out: | ||
| 7962 | dprintk("%s: status %d\n", __func__, status); | 8045 | dprintk("%s: status %d\n", __func__, status); |
| 7963 | rpc_put_task(task); | 8046 | rpc_put_task(task); |
| 7964 | return status; | 8047 | return status; |
| @@ -8386,6 +8469,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
| 8386 | .match_stateid = nfs4_match_stateid, | 8469 | .match_stateid = nfs4_match_stateid, |
| 8387 | .find_root_sec = nfs4_find_root_sec, | 8470 | .find_root_sec = nfs4_find_root_sec, |
| 8388 | .free_lock_state = nfs4_release_lockowner, | 8471 | .free_lock_state = nfs4_release_lockowner, |
| 8472 | .alloc_seqid = nfs_alloc_seqid, | ||
| 8389 | .call_sync_ops = &nfs40_call_sync_ops, | 8473 | .call_sync_ops = &nfs40_call_sync_ops, |
| 8390 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, | 8474 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
| 8391 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, | 8475 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
| @@ -8394,6 +8478,12 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
| 8394 | }; | 8478 | }; |
| 8395 | 8479 | ||
| 8396 | #if defined(CONFIG_NFS_V4_1) | 8480 | #if defined(CONFIG_NFS_V4_1) |
| 8481 | static struct nfs_seqid * | ||
| 8482 | nfs_alloc_no_seqid(struct nfs_seqid_counter *arg1, gfp_t arg2) | ||
| 8483 | { | ||
| 8484 | return NULL; | ||
| 8485 | } | ||
| 8486 | |||
| 8397 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | 8487 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { |
| 8398 | .minor_version = 1, | 8488 | .minor_version = 1, |
| 8399 | .init_caps = NFS_CAP_READDIRPLUS | 8489 | .init_caps = NFS_CAP_READDIRPLUS |
| @@ -8407,6 +8497,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | |||
| 8407 | .match_stateid = nfs41_match_stateid, | 8497 | .match_stateid = nfs41_match_stateid, |
| 8408 | .find_root_sec = nfs41_find_root_sec, | 8498 | .find_root_sec = nfs41_find_root_sec, |
| 8409 | .free_lock_state = nfs41_free_lock_state, | 8499 | .free_lock_state = nfs41_free_lock_state, |
| 8500 | .alloc_seqid = nfs_alloc_no_seqid, | ||
| 8410 | .call_sync_ops = &nfs41_call_sync_ops, | 8501 | .call_sync_ops = &nfs41_call_sync_ops, |
| 8411 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 8502 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
| 8412 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 8503 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
| @@ -8433,6 +8524,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { | |||
| 8433 | .find_root_sec = nfs41_find_root_sec, | 8524 | .find_root_sec = nfs41_find_root_sec, |
| 8434 | .free_lock_state = nfs41_free_lock_state, | 8525 | .free_lock_state = nfs41_free_lock_state, |
| 8435 | .call_sync_ops = &nfs41_call_sync_ops, | 8526 | .call_sync_ops = &nfs41_call_sync_ops, |
| 8527 | .alloc_seqid = nfs_alloc_no_seqid, | ||
| 8436 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 8528 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
| 8437 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | 8529 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, |
| 8438 | .state_renewal_ops = &nfs41_state_renewal_ops, | 8530 | .state_renewal_ops = &nfs41_state_renewal_ops, |
