| .. | .. |
|---|
| 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 = { |
|---|