.. | .. |
---|
130 | 130 | if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) |
---|
131 | 131 | return NULL; |
---|
132 | 132 | |
---|
| 133 | + label->lfs = 0; |
---|
| 134 | + label->pi = 0; |
---|
| 135 | + label->len = 0; |
---|
| 136 | + label->label = NULL; |
---|
| 137 | + |
---|
133 | 138 | err = security_dentry_init_security(dentry, sattr->ia_mode, |
---|
134 | 139 | &dentry->d_name, (void **)&label->label, &label->len); |
---|
135 | 140 | if (err == 0) |
---|
.. | .. |
---|
921 | 926 | out_noaction: |
---|
922 | 927 | return ret; |
---|
923 | 928 | session_recover: |
---|
| 929 | + set_bit(NFS4_SLOT_TBL_DRAINING, &session->fc_slot_table.slot_tbl_state); |
---|
924 | 930 | nfs4_schedule_session_recovery(session, status); |
---|
925 | 931 | dprintk("%s ERROR: %d Reset session\n", __func__, status); |
---|
926 | 932 | nfs41_sequence_free_slot(res); |
---|
.. | .. |
---|
1970 | 1976 | if (!data->rpc_done) { |
---|
1971 | 1977 | if (data->rpc_status) |
---|
1972 | 1978 | return ERR_PTR(data->rpc_status); |
---|
1973 | | - /* cached opens have already been processed */ |
---|
1974 | | - goto update; |
---|
| 1979 | + return nfs4_try_open_cached(data); |
---|
1975 | 1980 | } |
---|
1976 | 1981 | |
---|
1977 | 1982 | ret = nfs_refresh_inode(inode, &data->f_attr); |
---|
.. | .. |
---|
1980 | 1985 | |
---|
1981 | 1986 | if (data->o_res.delegation_type != 0) |
---|
1982 | 1987 | nfs4_opendata_check_deleg(data, state); |
---|
1983 | | -update: |
---|
| 1988 | + |
---|
1984 | 1989 | if (!update_open_stateid(state, &data->o_res.stateid, |
---|
1985 | 1990 | NULL, data->o_arg.fmode)) |
---|
1986 | 1991 | return ERR_PTR(-EAGAIN); |
---|
.. | .. |
---|
2121 | 2126 | } |
---|
2122 | 2127 | |
---|
2123 | 2128 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, |
---|
2124 | | - fmode_t fmode) |
---|
| 2129 | + fmode_t fmode) |
---|
2125 | 2130 | { |
---|
2126 | 2131 | struct nfs4_state *newstate; |
---|
| 2132 | + struct nfs_server *server = NFS_SB(opendata->dentry->d_sb); |
---|
| 2133 | + int openflags = opendata->o_arg.open_flags; |
---|
2127 | 2134 | int ret; |
---|
2128 | 2135 | |
---|
2129 | 2136 | if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) |
---|
2130 | 2137 | return 0; |
---|
2131 | | - opendata->o_arg.open_flags = 0; |
---|
2132 | 2138 | opendata->o_arg.fmode = fmode; |
---|
2133 | | - opendata->o_arg.share_access = nfs4_map_atomic_open_share( |
---|
2134 | | - NFS_SB(opendata->dentry->d_sb), |
---|
2135 | | - fmode, 0); |
---|
| 2139 | + opendata->o_arg.share_access = |
---|
| 2140 | + nfs4_map_atomic_open_share(server, fmode, openflags); |
---|
2136 | 2141 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); |
---|
2137 | 2142 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); |
---|
2138 | 2143 | nfs4_init_opendata_res(opendata); |
---|
.. | .. |
---|
2708 | 2713 | struct nfs4_opendata *opendata; |
---|
2709 | 2714 | int ret; |
---|
2710 | 2715 | |
---|
2711 | | - opendata = nfs4_open_recoverdata_alloc(ctx, state, |
---|
2712 | | - NFS4_OPEN_CLAIM_FH); |
---|
| 2716 | + opendata = nfs4_open_recoverdata_alloc(ctx, state, NFS4_OPEN_CLAIM_FH); |
---|
2713 | 2717 | if (IS_ERR(opendata)) |
---|
2714 | 2718 | return PTR_ERR(opendata); |
---|
| 2719 | + /* |
---|
| 2720 | + * We're not recovering a delegation, so ask for no delegation. |
---|
| 2721 | + * Otherwise the recovery thread could deadlock with an outstanding |
---|
| 2722 | + * delegation return. |
---|
| 2723 | + */ |
---|
| 2724 | + opendata->o_arg.open_flags = O_DIRECT; |
---|
2715 | 2725 | ret = nfs4_open_recover(opendata, state); |
---|
2716 | 2726 | if (ret == -ESTALE) |
---|
2717 | 2727 | d_drop(ctx->dentry); |
---|
.. | .. |
---|
3793 | 3803 | int open_flags, struct iattr *attr, int *opened) |
---|
3794 | 3804 | { |
---|
3795 | 3805 | struct nfs4_state *state; |
---|
3796 | | - struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; |
---|
| 3806 | + struct nfs4_label l, *label; |
---|
3797 | 3807 | |
---|
3798 | 3808 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); |
---|
3799 | 3809 | |
---|
.. | .. |
---|
4557 | 4567 | int flags) |
---|
4558 | 4568 | { |
---|
4559 | 4569 | struct nfs_server *server = NFS_SERVER(dir); |
---|
4560 | | - struct nfs4_label l, *ilabel = NULL; |
---|
| 4570 | + struct nfs4_label l, *ilabel; |
---|
4561 | 4571 | struct nfs_open_context *ctx; |
---|
4562 | 4572 | struct nfs4_state *state; |
---|
4563 | 4573 | int status = 0; |
---|
.. | .. |
---|
4916 | 4926 | struct nfs4_exception exception = { |
---|
4917 | 4927 | .interruptible = true, |
---|
4918 | 4928 | }; |
---|
4919 | | - struct nfs4_label l, *label = NULL; |
---|
| 4929 | + struct nfs4_label l, *label; |
---|
4920 | 4930 | int err; |
---|
4921 | 4931 | |
---|
4922 | 4932 | label = nfs4_label_init_security(dir, dentry, sattr, &l); |
---|
.. | .. |
---|
4957 | 4967 | struct nfs4_exception exception = { |
---|
4958 | 4968 | .interruptible = true, |
---|
4959 | 4969 | }; |
---|
4960 | | - struct nfs4_label l, *label = NULL; |
---|
| 4970 | + struct nfs4_label l, *label; |
---|
4961 | 4971 | int err; |
---|
4962 | 4972 | |
---|
4963 | 4973 | label = nfs4_label_init_security(dir, dentry, sattr, &l); |
---|
.. | .. |
---|
5078 | 5088 | struct nfs4_exception exception = { |
---|
5079 | 5089 | .interruptible = true, |
---|
5080 | 5090 | }; |
---|
5081 | | - struct nfs4_label l, *label = NULL; |
---|
| 5091 | + struct nfs4_label l, *label; |
---|
5082 | 5092 | int err; |
---|
5083 | 5093 | |
---|
5084 | 5094 | label = nfs4_label_init_security(dir, dentry, sattr, &l); |
---|
.. | .. |
---|
5854 | 5864 | out_ok: |
---|
5855 | 5865 | ret = res.acl_len; |
---|
5856 | 5866 | out_free: |
---|
5857 | | - for (i = 0; i < npages; i++) |
---|
5858 | | - if (pages[i]) |
---|
5859 | | - __free_page(pages[i]); |
---|
| 5867 | + while (--i >= 0) |
---|
| 5868 | + __free_page(pages[i]); |
---|
5860 | 5869 | if (res.acl_scratch) |
---|
5861 | 5870 | __free_page(res.acl_scratch); |
---|
5862 | 5871 | kfree(pages); |
---|
.. | .. |
---|
7037 | 7046 | } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid)) |
---|
7038 | 7047 | goto out_restart; |
---|
7039 | 7048 | break; |
---|
7040 | | - case -NFS4ERR_BAD_STATEID: |
---|
7041 | 7049 | case -NFS4ERR_OLD_STATEID: |
---|
| 7050 | + if (data->arg.new_lock_owner != 0 && |
---|
| 7051 | + nfs4_refresh_open_old_stateid(&data->arg.open_stateid, |
---|
| 7052 | + lsp->ls_state)) |
---|
| 7053 | + goto out_restart; |
---|
| 7054 | + if (nfs4_refresh_lock_old_stateid(&data->arg.lock_stateid, lsp)) |
---|
| 7055 | + goto out_restart; |
---|
| 7056 | + fallthrough; |
---|
| 7057 | + case -NFS4ERR_BAD_STATEID: |
---|
7042 | 7058 | case -NFS4ERR_STALE_STATEID: |
---|
7043 | 7059 | case -NFS4ERR_EXPIRED: |
---|
7044 | 7060 | if (data->arg.new_lock_owner != 0) { |
---|
.. | .. |
---|
10378 | 10394 | return error + error2 + error3; |
---|
10379 | 10395 | } |
---|
10380 | 10396 | |
---|
| 10397 | +static void nfs4_enable_swap(struct inode *inode) |
---|
| 10398 | +{ |
---|
| 10399 | + /* The state manager thread must always be running. |
---|
| 10400 | + * It will notice the client is a swapper, and stay put. |
---|
| 10401 | + */ |
---|
| 10402 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
---|
| 10403 | + |
---|
| 10404 | + nfs4_schedule_state_manager(clp); |
---|
| 10405 | +} |
---|
| 10406 | + |
---|
| 10407 | +static void nfs4_disable_swap(struct inode *inode) |
---|
| 10408 | +{ |
---|
| 10409 | + /* The state manager thread will now exit once it is |
---|
| 10410 | + * woken. |
---|
| 10411 | + */ |
---|
| 10412 | + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
---|
| 10413 | + |
---|
| 10414 | + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
---|
| 10415 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); |
---|
| 10416 | + wake_up_var(&clp->cl_state); |
---|
| 10417 | +} |
---|
| 10418 | + |
---|
10381 | 10419 | static const struct inode_operations nfs4_dir_inode_operations = { |
---|
10382 | 10420 | .create = nfs_create, |
---|
10383 | 10421 | .lookup = nfs_lookup, |
---|
.. | .. |
---|
10454 | 10492 | .free_client = nfs4_free_client, |
---|
10455 | 10493 | .create_server = nfs4_create_server, |
---|
10456 | 10494 | .clone_server = nfs_clone_server, |
---|
| 10495 | + .enable_swap = nfs4_enable_swap, |
---|
| 10496 | + .disable_swap = nfs4_disable_swap, |
---|
10457 | 10497 | }; |
---|
10458 | 10498 | |
---|
10459 | 10499 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |
---|