diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 192 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 131 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 52 |
3 files changed, 179 insertions, 196 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3ecb7da220f5..857125705b6f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2935,43 +2935,17 @@ nfs4_set_lock_task_retry(unsigned long timeout) | |||
2935 | return timeout; | 2935 | return timeout; |
2936 | } | 2936 | } |
2937 | 2937 | ||
2938 | static inline int | ||
2939 | nfs4_lck_type(int cmd, struct file_lock *request) | ||
2940 | { | ||
2941 | /* set lock type */ | ||
2942 | switch (request->fl_type) { | ||
2943 | case F_RDLCK: | ||
2944 | return IS_SETLKW(cmd) ? NFS4_READW_LT : NFS4_READ_LT; | ||
2945 | case F_WRLCK: | ||
2946 | return IS_SETLKW(cmd) ? NFS4_WRITEW_LT : NFS4_WRITE_LT; | ||
2947 | case F_UNLCK: | ||
2948 | return NFS4_WRITE_LT; | ||
2949 | } | ||
2950 | BUG(); | ||
2951 | return 0; | ||
2952 | } | ||
2953 | |||
2954 | static inline uint64_t | ||
2955 | nfs4_lck_length(struct file_lock *request) | ||
2956 | { | ||
2957 | if (request->fl_end == OFFSET_MAX) | ||
2958 | return ~(uint64_t)0; | ||
2959 | return request->fl_end - request->fl_start + 1; | ||
2960 | } | ||
2961 | |||
2962 | static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request) | 2938 | static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
2963 | { | 2939 | { |
2964 | struct inode *inode = state->inode; | 2940 | struct inode *inode = state->inode; |
2965 | struct nfs_server *server = NFS_SERVER(inode); | 2941 | struct nfs_server *server = NFS_SERVER(inode); |
2966 | struct nfs4_client *clp = server->nfs4_state; | 2942 | struct nfs4_client *clp = server->nfs4_state; |
2967 | struct nfs_lockargs arg = { | 2943 | struct nfs_lockt_args arg = { |
2968 | .fh = NFS_FH(inode), | 2944 | .fh = NFS_FH(inode), |
2969 | .type = nfs4_lck_type(cmd, request), | 2945 | .fl = request, |
2970 | .offset = request->fl_start, | ||
2971 | .length = nfs4_lck_length(request), | ||
2972 | }; | 2946 | }; |
2973 | struct nfs_lockres res = { | 2947 | struct nfs_lockt_res res = { |
2974 | .server = server, | 2948 | .denied = request, |
2975 | }; | 2949 | }; |
2976 | struct rpc_message msg = { | 2950 | struct rpc_message msg = { |
2977 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT], | 2951 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT], |
@@ -2979,36 +2953,23 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
2979 | .rpc_resp = &res, | 2953 | .rpc_resp = &res, |
2980 | .rpc_cred = state->owner->so_cred, | 2954 | .rpc_cred = state->owner->so_cred, |
2981 | }; | 2955 | }; |
2982 | struct nfs_lowner nlo; | ||
2983 | struct nfs4_lock_state *lsp; | 2956 | struct nfs4_lock_state *lsp; |
2984 | int status; | 2957 | int status; |
2985 | 2958 | ||
2986 | down_read(&clp->cl_sem); | 2959 | down_read(&clp->cl_sem); |
2987 | nlo.clientid = clp->cl_clientid; | 2960 | arg.lock_owner.clientid = clp->cl_clientid; |
2988 | status = nfs4_set_lock_state(state, request); | 2961 | status = nfs4_set_lock_state(state, request); |
2989 | if (status != 0) | 2962 | if (status != 0) |
2990 | goto out; | 2963 | goto out; |
2991 | lsp = request->fl_u.nfs4_fl.owner; | 2964 | lsp = request->fl_u.nfs4_fl.owner; |
2992 | nlo.id = lsp->ls_id; | 2965 | arg.lock_owner.id = lsp->ls_id; |
2993 | arg.u.lockt = &nlo; | ||
2994 | status = rpc_call_sync(server->client, &msg, 0); | 2966 | status = rpc_call_sync(server->client, &msg, 0); |
2995 | if (!status) { | 2967 | switch (status) { |
2996 | request->fl_type = F_UNLCK; | 2968 | case 0: |
2997 | } else if (status == -NFS4ERR_DENIED) { | 2969 | request->fl_type = F_UNLCK; |
2998 | int64_t len, start, end; | 2970 | break; |
2999 | start = res.u.denied.offset; | 2971 | case -NFS4ERR_DENIED: |
3000 | len = res.u.denied.length; | 2972 | status = 0; |
3001 | end = start + len - 1; | ||
3002 | if (end < 0 || len == 0) | ||
3003 | request->fl_end = OFFSET_MAX; | ||
3004 | else | ||
3005 | request->fl_end = (loff_t)end; | ||
3006 | request->fl_start = (loff_t)start; | ||
3007 | request->fl_type = F_WRLCK; | ||
3008 | if (res.u.denied.type & 1) | ||
3009 | request->fl_type = F_RDLCK; | ||
3010 | request->fl_pid = 0; | ||
3011 | status = 0; | ||
3012 | } | 2973 | } |
3013 | out: | 2974 | out: |
3014 | up_read(&clp->cl_sem); | 2975 | up_read(&clp->cl_sem); |
@@ -3048,17 +3009,42 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
3048 | } | 3009 | } |
3049 | 3010 | ||
3050 | struct nfs4_unlockdata { | 3011 | struct nfs4_unlockdata { |
3051 | struct nfs_lockargs arg; | 3012 | struct nfs_locku_args arg; |
3052 | struct nfs_locku_opargs luargs; | 3013 | struct nfs_locku_res res; |
3053 | struct nfs_lockres res; | ||
3054 | struct nfs4_lock_state *lsp; | 3014 | struct nfs4_lock_state *lsp; |
3055 | struct nfs_open_context *ctx; | 3015 | struct nfs_open_context *ctx; |
3016 | struct file_lock fl; | ||
3017 | const struct nfs_server *server; | ||
3056 | }; | 3018 | }; |
3057 | 3019 | ||
3020 | static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, | ||
3021 | struct nfs_open_context *ctx, | ||
3022 | struct nfs4_lock_state *lsp, | ||
3023 | struct nfs_seqid *seqid) | ||
3024 | { | ||
3025 | struct nfs4_unlockdata *p; | ||
3026 | struct inode *inode = lsp->ls_state->inode; | ||
3027 | |||
3028 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
3029 | if (p == NULL) | ||
3030 | return NULL; | ||
3031 | p->arg.fh = NFS_FH(inode); | ||
3032 | p->arg.fl = &p->fl; | ||
3033 | p->arg.seqid = seqid; | ||
3034 | p->arg.stateid = &lsp->ls_stateid; | ||
3035 | p->lsp = lsp; | ||
3036 | atomic_inc(&lsp->ls_count); | ||
3037 | /* Ensure we don't close file until we're done freeing locks! */ | ||
3038 | p->ctx = get_nfs_open_context(ctx); | ||
3039 | memcpy(&p->fl, fl, sizeof(p->fl)); | ||
3040 | p->server = NFS_SERVER(inode); | ||
3041 | return p; | ||
3042 | } | ||
3043 | |||
3058 | static void nfs4_locku_release_calldata(void *data) | 3044 | static void nfs4_locku_release_calldata(void *data) |
3059 | { | 3045 | { |
3060 | struct nfs4_unlockdata *calldata = data; | 3046 | struct nfs4_unlockdata *calldata = data; |
3061 | nfs_free_seqid(calldata->luargs.seqid); | 3047 | nfs_free_seqid(calldata->arg.seqid); |
3062 | nfs4_put_lock_state(calldata->lsp); | 3048 | nfs4_put_lock_state(calldata->lsp); |
3063 | put_nfs_open_context(calldata->ctx); | 3049 | put_nfs_open_context(calldata->ctx); |
3064 | kfree(calldata); | 3050 | kfree(calldata); |
@@ -3070,19 +3056,19 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3070 | 3056 | ||
3071 | if (RPC_ASSASSINATED(task)) | 3057 | if (RPC_ASSASSINATED(task)) |
3072 | return; | 3058 | return; |
3073 | nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); | 3059 | nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid); |
3074 | switch (task->tk_status) { | 3060 | switch (task->tk_status) { |
3075 | case 0: | 3061 | case 0: |
3076 | memcpy(calldata->lsp->ls_stateid.data, | 3062 | memcpy(calldata->lsp->ls_stateid.data, |
3077 | calldata->res.u.stateid.data, | 3063 | calldata->res.stateid.data, |
3078 | sizeof(calldata->lsp->ls_stateid.data)); | 3064 | sizeof(calldata->lsp->ls_stateid.data)); |
3079 | break; | 3065 | break; |
3080 | case -NFS4ERR_STALE_STATEID: | 3066 | case -NFS4ERR_STALE_STATEID: |
3081 | case -NFS4ERR_EXPIRED: | 3067 | case -NFS4ERR_EXPIRED: |
3082 | nfs4_schedule_state_recovery(calldata->res.server->nfs4_state); | 3068 | nfs4_schedule_state_recovery(calldata->server->nfs4_state); |
3083 | break; | 3069 | break; |
3084 | default: | 3070 | default: |
3085 | if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { | 3071 | if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) { |
3086 | rpc_restart_call(task); | 3072 | rpc_restart_call(task); |
3087 | } | 3073 | } |
3088 | } | 3074 | } |
@@ -3097,10 +3083,8 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
3097 | .rpc_resp = &calldata->res, | 3083 | .rpc_resp = &calldata->res, |
3098 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, | 3084 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, |
3099 | }; | 3085 | }; |
3100 | int status; | ||
3101 | 3086 | ||
3102 | status = nfs_wait_on_sequence(calldata->luargs.seqid, task); | 3087 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
3103 | if (status != 0) | ||
3104 | return; | 3088 | return; |
3105 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { | 3089 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { |
3106 | /* Note: exit _without_ running nfs4_locku_done */ | 3090 | /* Note: exit _without_ running nfs4_locku_done */ |
@@ -3121,43 +3105,32 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
3121 | struct nfs4_unlockdata *calldata; | 3105 | struct nfs4_unlockdata *calldata; |
3122 | struct inode *inode = state->inode; | 3106 | struct inode *inode = state->inode; |
3123 | struct nfs_server *server = NFS_SERVER(inode); | 3107 | struct nfs_server *server = NFS_SERVER(inode); |
3108 | struct nfs_seqid *seqid; | ||
3124 | struct nfs4_lock_state *lsp; | 3109 | struct nfs4_lock_state *lsp; |
3125 | struct rpc_task *task; | 3110 | struct rpc_task *task; |
3126 | int status = 0; | 3111 | int status = 0; |
3127 | 3112 | ||
3128 | /* Is this a delegated lock? */ | 3113 | /* Is this a delegated lock? */ |
3129 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | 3114 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) |
3130 | goto out; | 3115 | goto out_unlock; |
3116 | /* Is this open_owner holding any locks on the server? */ | ||
3117 | if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) | ||
3118 | goto out_unlock; | ||
3131 | 3119 | ||
3132 | status = nfs4_set_lock_state(state, request); | 3120 | status = nfs4_set_lock_state(state, request); |
3133 | if (status != 0) | 3121 | if (status != 0) |
3134 | goto out; | 3122 | goto out_unlock; |
3135 | lsp = request->fl_u.nfs4_fl.owner; | 3123 | lsp = request->fl_u.nfs4_fl.owner; |
3136 | /* We might have lost the locks! */ | ||
3137 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) | ||
3138 | goto out; | ||
3139 | status = -ENOMEM; | 3124 | status = -ENOMEM; |
3140 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); | 3125 | seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
3126 | if (seqid == NULL) | ||
3127 | goto out_unlock; | ||
3128 | calldata = nfs4_alloc_unlockdata(request, request->fl_file->private_data, | ||
3129 | lsp, seqid); | ||
3141 | if (calldata == NULL) | 3130 | if (calldata == NULL) |
3142 | goto out; | 3131 | goto out_free_seqid; |
3143 | calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 3132 | /* Unlock _before_ we do the RPC call */ |
3144 | if (calldata->luargs.seqid == NULL) { | 3133 | do_vfs_lock(request->fl_file, request); |
3145 | kfree(calldata); | ||
3146 | goto out; | ||
3147 | } | ||
3148 | calldata->luargs.stateid = &lsp->ls_stateid; | ||
3149 | calldata->arg.fh = NFS_FH(inode); | ||
3150 | calldata->arg.type = nfs4_lck_type(cmd, request); | ||
3151 | calldata->arg.offset = request->fl_start; | ||
3152 | calldata->arg.length = nfs4_lck_length(request); | ||
3153 | calldata->arg.u.locku = &calldata->luargs; | ||
3154 | calldata->res.server = server; | ||
3155 | calldata->lsp = lsp; | ||
3156 | atomic_inc(&lsp->ls_count); | ||
3157 | |||
3158 | /* Ensure we don't close file until we're done freeing locks! */ | ||
3159 | calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data); | ||
3160 | |||
3161 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_locku_ops, calldata); | 3134 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_locku_ops, calldata); |
3162 | if (!IS_ERR(task)) { | 3135 | if (!IS_ERR(task)) { |
3163 | status = nfs4_wait_for_completion_rpc_task(task); | 3136 | status = nfs4_wait_for_completion_rpc_task(task); |
@@ -3166,7 +3139,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
3166 | status = PTR_ERR(task); | 3139 | status = PTR_ERR(task); |
3167 | nfs4_locku_release_calldata(calldata); | 3140 | nfs4_locku_release_calldata(calldata); |
3168 | } | 3141 | } |
3169 | out: | 3142 | return status; |
3143 | out_free_seqid: | ||
3144 | nfs_free_seqid(seqid); | ||
3145 | out_unlock: | ||
3170 | do_vfs_lock(request->fl_file, request); | 3146 | do_vfs_lock(request->fl_file, request); |
3171 | return status; | 3147 | return status; |
3172 | } | 3148 | } |
@@ -3176,27 +3152,19 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
3176 | struct inode *inode = state->inode; | 3152 | struct inode *inode = state->inode; |
3177 | struct nfs_server *server = NFS_SERVER(inode); | 3153 | struct nfs_server *server = NFS_SERVER(inode); |
3178 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; | 3154 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; |
3179 | struct nfs_lock_opargs largs = { | 3155 | struct nfs_lock_args arg = { |
3156 | .fh = NFS_FH(inode), | ||
3157 | .fl = request, | ||
3180 | .lock_stateid = &lsp->ls_stateid, | 3158 | .lock_stateid = &lsp->ls_stateid, |
3181 | .open_stateid = &state->stateid, | 3159 | .open_stateid = &state->stateid, |
3182 | .lock_owner = { | 3160 | .lock_owner = { |
3183 | .clientid = server->nfs4_state->cl_clientid, | 3161 | .clientid = server->nfs4_state->cl_clientid, |
3184 | .id = lsp->ls_id, | 3162 | .id = lsp->ls_id, |
3185 | }, | 3163 | }, |
3164 | .block = (IS_SETLKW(cmd)) ? 1 : 0, | ||
3186 | .reclaim = reclaim, | 3165 | .reclaim = reclaim, |
3187 | }; | 3166 | }; |
3188 | struct nfs_lockargs arg = { | 3167 | struct nfs_lock_res res; |
3189 | .fh = NFS_FH(inode), | ||
3190 | .type = nfs4_lck_type(cmd, request), | ||
3191 | .offset = request->fl_start, | ||
3192 | .length = nfs4_lck_length(request), | ||
3193 | .u = { | ||
3194 | .lock = &largs, | ||
3195 | }, | ||
3196 | }; | ||
3197 | struct nfs_lockres res = { | ||
3198 | .server = server, | ||
3199 | }; | ||
3200 | struct rpc_message msg = { | 3168 | struct rpc_message msg = { |
3201 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], | 3169 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], |
3202 | .rpc_argp = &arg, | 3170 | .rpc_argp = &arg, |
@@ -3205,37 +3173,37 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
3205 | }; | 3173 | }; |
3206 | int status = -ENOMEM; | 3174 | int status = -ENOMEM; |
3207 | 3175 | ||
3208 | largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 3176 | arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
3209 | if (largs.lock_seqid == NULL) | 3177 | if (arg.lock_seqid == NULL) |
3210 | return -ENOMEM; | 3178 | return -ENOMEM; |
3211 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { | 3179 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { |
3212 | struct nfs4_state_owner *owner = state->owner; | 3180 | struct nfs4_state_owner *owner = state->owner; |
3213 | 3181 | ||
3214 | largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid); | 3182 | arg.open_seqid = nfs_alloc_seqid(&owner->so_seqid); |
3215 | if (largs.open_seqid == NULL) | 3183 | if (arg.open_seqid == NULL) |
3216 | goto out; | 3184 | goto out; |
3217 | largs.new_lock_owner = 1; | 3185 | arg.new_lock_owner = 1; |
3218 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3186 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
3219 | /* increment open seqid on success, and seqid mutating errors */ | 3187 | /* increment open seqid on success, and seqid mutating errors */ |
3220 | if (largs.new_lock_owner != 0) { | 3188 | if (arg.new_lock_owner != 0) { |
3221 | nfs_increment_open_seqid(status, largs.open_seqid); | 3189 | nfs_increment_open_seqid(status, arg.open_seqid); |
3222 | if (status == 0) | 3190 | if (status == 0) |
3223 | nfs_confirm_seqid(&lsp->ls_seqid, 0); | 3191 | nfs_confirm_seqid(&lsp->ls_seqid, 0); |
3224 | } | 3192 | } |
3225 | nfs_free_seqid(largs.open_seqid); | 3193 | nfs_free_seqid(arg.open_seqid); |
3226 | } else | 3194 | } else |
3227 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3195 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
3228 | /* increment lock seqid on success, and seqid mutating errors*/ | 3196 | /* increment lock seqid on success, and seqid mutating errors*/ |
3229 | nfs_increment_lock_seqid(status, largs.lock_seqid); | 3197 | nfs_increment_lock_seqid(status, arg.lock_seqid); |
3230 | /* save the returned stateid. */ | 3198 | /* save the returned stateid. */ |
3231 | if (status == 0) { | 3199 | if (status == 0) { |
3232 | memcpy(lsp->ls_stateid.data, res.u.stateid.data, | 3200 | memcpy(lsp->ls_stateid.data, res.stateid.data, |
3233 | sizeof(lsp->ls_stateid.data)); | 3201 | sizeof(lsp->ls_stateid.data)); |
3234 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | 3202 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; |
3235 | } else if (status == -NFS4ERR_DENIED) | 3203 | } else if (status == -NFS4ERR_DENIED) |
3236 | status = -EAGAIN; | 3204 | status = -EAGAIN; |
3237 | out: | 3205 | out: |
3238 | nfs_free_seqid(largs.lock_seqid); | 3206 | nfs_free_seqid(arg.lock_seqid); |
3239 | return status; | 3207 | return status; |
3240 | } | 3208 | } |
3241 | 3209 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 3100172822c9..a7b5de899c6d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -742,69 +742,80 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name) | |||
742 | return 0; | 742 | return 0; |
743 | } | 743 | } |
744 | 744 | ||
745 | static inline int nfs4_lock_type(struct file_lock *fl, int block) | ||
746 | { | ||
747 | if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) | ||
748 | return block ? NFS4_READW_LT : NFS4_READ_LT; | ||
749 | return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; | ||
750 | } | ||
751 | |||
752 | static inline uint64_t nfs4_lock_length(struct file_lock *fl) | ||
753 | { | ||
754 | if (fl->fl_end == OFFSET_MAX) | ||
755 | return ~(uint64_t)0; | ||
756 | return fl->fl_end - fl->fl_start + 1; | ||
757 | } | ||
758 | |||
745 | /* | 759 | /* |
746 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 | 760 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 |
747 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 | 761 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 |
748 | */ | 762 | */ |
749 | static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | 763 | static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args) |
750 | { | 764 | { |
751 | uint32_t *p; | 765 | uint32_t *p; |
752 | struct nfs_lock_opargs *opargs = arg->u.lock; | ||
753 | 766 | ||
754 | RESERVE_SPACE(32); | 767 | RESERVE_SPACE(32); |
755 | WRITE32(OP_LOCK); | 768 | WRITE32(OP_LOCK); |
756 | WRITE32(arg->type); | 769 | WRITE32(nfs4_lock_type(args->fl, args->block)); |
757 | WRITE32(opargs->reclaim); | 770 | WRITE32(args->reclaim); |
758 | WRITE64(arg->offset); | 771 | WRITE64(args->fl->fl_start); |
759 | WRITE64(arg->length); | 772 | WRITE64(nfs4_lock_length(args->fl)); |
760 | WRITE32(opargs->new_lock_owner); | 773 | WRITE32(args->new_lock_owner); |
761 | if (opargs->new_lock_owner){ | 774 | if (args->new_lock_owner){ |
762 | RESERVE_SPACE(40); | 775 | RESERVE_SPACE(40); |
763 | WRITE32(opargs->open_seqid->sequence->counter); | 776 | WRITE32(args->open_seqid->sequence->counter); |
764 | WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data)); | 777 | WRITEMEM(args->open_stateid->data, sizeof(args->open_stateid->data)); |
765 | WRITE32(opargs->lock_seqid->sequence->counter); | 778 | WRITE32(args->lock_seqid->sequence->counter); |
766 | WRITE64(opargs->lock_owner.clientid); | 779 | WRITE64(args->lock_owner.clientid); |
767 | WRITE32(4); | 780 | WRITE32(4); |
768 | WRITE32(opargs->lock_owner.id); | 781 | WRITE32(args->lock_owner.id); |
769 | } | 782 | } |
770 | else { | 783 | else { |
771 | RESERVE_SPACE(20); | 784 | RESERVE_SPACE(20); |
772 | WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data)); | 785 | WRITEMEM(args->lock_stateid->data, sizeof(args->lock_stateid->data)); |
773 | WRITE32(opargs->lock_seqid->sequence->counter); | 786 | WRITE32(args->lock_seqid->sequence->counter); |
774 | } | 787 | } |
775 | 788 | ||
776 | return 0; | 789 | return 0; |
777 | } | 790 | } |
778 | 791 | ||
779 | static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | 792 | static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args) |
780 | { | 793 | { |
781 | uint32_t *p; | 794 | uint32_t *p; |
782 | struct nfs_lowner *opargs = arg->u.lockt; | ||
783 | 795 | ||
784 | RESERVE_SPACE(40); | 796 | RESERVE_SPACE(40); |
785 | WRITE32(OP_LOCKT); | 797 | WRITE32(OP_LOCKT); |
786 | WRITE32(arg->type); | 798 | WRITE32(nfs4_lock_type(args->fl, 0)); |
787 | WRITE64(arg->offset); | 799 | WRITE64(args->fl->fl_start); |
788 | WRITE64(arg->length); | 800 | WRITE64(nfs4_lock_length(args->fl)); |
789 | WRITE64(opargs->clientid); | 801 | WRITE64(args->lock_owner.clientid); |
790 | WRITE32(4); | 802 | WRITE32(4); |
791 | WRITE32(opargs->id); | 803 | WRITE32(args->lock_owner.id); |
792 | 804 | ||
793 | return 0; | 805 | return 0; |
794 | } | 806 | } |
795 | 807 | ||
796 | static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | 808 | static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args) |
797 | { | 809 | { |
798 | uint32_t *p; | 810 | uint32_t *p; |
799 | struct nfs_locku_opargs *opargs = arg->u.locku; | ||
800 | 811 | ||
801 | RESERVE_SPACE(44); | 812 | RESERVE_SPACE(44); |
802 | WRITE32(OP_LOCKU); | 813 | WRITE32(OP_LOCKU); |
803 | WRITE32(arg->type); | 814 | WRITE32(nfs4_lock_type(args->fl, 0)); |
804 | WRITE32(opargs->seqid->sequence->counter); | 815 | WRITE32(args->seqid->sequence->counter); |
805 | WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data)); | 816 | WRITEMEM(args->stateid->data, sizeof(args->stateid->data)); |
806 | WRITE64(arg->offset); | 817 | WRITE64(args->fl->fl_start); |
807 | WRITE64(arg->length); | 818 | WRITE64(nfs4_lock_length(args->fl)); |
808 | 819 | ||
809 | return 0; | 820 | return 0; |
810 | } | 821 | } |
@@ -1596,21 +1607,20 @@ out: | |||
1596 | /* | 1607 | /* |
1597 | * Encode a LOCK request | 1608 | * Encode a LOCK request |
1598 | */ | 1609 | */ |
1599 | static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) | 1610 | static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_args *args) |
1600 | { | 1611 | { |
1601 | struct xdr_stream xdr; | 1612 | struct xdr_stream xdr; |
1602 | struct compound_hdr hdr = { | 1613 | struct compound_hdr hdr = { |
1603 | .nops = 2, | 1614 | .nops = 2, |
1604 | }; | 1615 | }; |
1605 | struct nfs_lock_opargs *opargs = args->u.lock; | ||
1606 | int status; | 1616 | int status; |
1607 | 1617 | ||
1608 | status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task); | 1618 | status = nfs_wait_on_sequence(args->lock_seqid, req->rq_task); |
1609 | if (status != 0) | 1619 | if (status != 0) |
1610 | goto out; | 1620 | goto out; |
1611 | /* Do we need to do an open_to_lock_owner? */ | 1621 | /* Do we need to do an open_to_lock_owner? */ |
1612 | if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED) | 1622 | if (args->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED) |
1613 | opargs->new_lock_owner = 0; | 1623 | args->new_lock_owner = 0; |
1614 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1624 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1615 | encode_compound_hdr(&xdr, &hdr); | 1625 | encode_compound_hdr(&xdr, &hdr); |
1616 | status = encode_putfh(&xdr, args->fh); | 1626 | status = encode_putfh(&xdr, args->fh); |
@@ -1624,7 +1634,7 @@ out: | |||
1624 | /* | 1634 | /* |
1625 | * Encode a LOCKT request | 1635 | * Encode a LOCKT request |
1626 | */ | 1636 | */ |
1627 | static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) | 1637 | static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockt_args *args) |
1628 | { | 1638 | { |
1629 | struct xdr_stream xdr; | 1639 | struct xdr_stream xdr; |
1630 | struct compound_hdr hdr = { | 1640 | struct compound_hdr hdr = { |
@@ -1645,7 +1655,7 @@ out: | |||
1645 | /* | 1655 | /* |
1646 | * Encode a LOCKU request | 1656 | * Encode a LOCKU request |
1647 | */ | 1657 | */ |
1648 | static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) | 1658 | static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_locku_args *args) |
1649 | { | 1659 | { |
1650 | struct xdr_stream xdr; | 1660 | struct xdr_stream xdr; |
1651 | struct compound_hdr hdr = { | 1661 | struct compound_hdr hdr = { |
@@ -2949,55 +2959,64 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) | |||
2949 | /* | 2959 | /* |
2950 | * We create the owner, so we know a proper owner.id length is 4. | 2960 | * We create the owner, so we know a proper owner.id length is 4. |
2951 | */ | 2961 | */ |
2952 | static int decode_lock_denied (struct xdr_stream *xdr, struct nfs_lock_denied *denied) | 2962 | static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) |
2953 | { | 2963 | { |
2964 | uint64_t offset, length, clientid; | ||
2954 | uint32_t *p; | 2965 | uint32_t *p; |
2955 | uint32_t namelen; | 2966 | uint32_t namelen, type; |
2956 | 2967 | ||
2957 | READ_BUF(32); | 2968 | READ_BUF(32); |
2958 | READ64(denied->offset); | 2969 | READ64(offset); |
2959 | READ64(denied->length); | 2970 | READ64(length); |
2960 | READ32(denied->type); | 2971 | READ32(type); |
2961 | READ64(denied->owner.clientid); | 2972 | if (fl != NULL) { |
2973 | fl->fl_start = (loff_t)offset; | ||
2974 | fl->fl_end = fl->fl_start + (loff_t)length - 1; | ||
2975 | if (length == ~(uint64_t)0) | ||
2976 | fl->fl_end = OFFSET_MAX; | ||
2977 | fl->fl_type = F_WRLCK; | ||
2978 | if (type & 1) | ||
2979 | fl->fl_type = F_RDLCK; | ||
2980 | fl->fl_pid = 0; | ||
2981 | } | ||
2982 | READ64(clientid); | ||
2962 | READ32(namelen); | 2983 | READ32(namelen); |
2963 | READ_BUF(namelen); | 2984 | READ_BUF(namelen); |
2964 | if (namelen == 4) | ||
2965 | READ32(denied->owner.id); | ||
2966 | return -NFS4ERR_DENIED; | 2985 | return -NFS4ERR_DENIED; |
2967 | } | 2986 | } |
2968 | 2987 | ||
2969 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res) | 2988 | static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) |
2970 | { | 2989 | { |
2971 | uint32_t *p; | 2990 | uint32_t *p; |
2972 | int status; | 2991 | int status; |
2973 | 2992 | ||
2974 | status = decode_op_hdr(xdr, OP_LOCK); | 2993 | status = decode_op_hdr(xdr, OP_LOCK); |
2975 | if (status == 0) { | 2994 | if (status == 0) { |
2976 | READ_BUF(sizeof(res->u.stateid.data)); | 2995 | READ_BUF(sizeof(res->stateid.data)); |
2977 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); | 2996 | COPYMEM(res->stateid.data, sizeof(res->stateid.data)); |
2978 | } else if (status == -NFS4ERR_DENIED) | 2997 | } else if (status == -NFS4ERR_DENIED) |
2979 | return decode_lock_denied(xdr, &res->u.denied); | 2998 | return decode_lock_denied(xdr, NULL); |
2980 | return status; | 2999 | return status; |
2981 | } | 3000 | } |
2982 | 3001 | ||
2983 | static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockres *res) | 3002 | static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) |
2984 | { | 3003 | { |
2985 | int status; | 3004 | int status; |
2986 | status = decode_op_hdr(xdr, OP_LOCKT); | 3005 | status = decode_op_hdr(xdr, OP_LOCKT); |
2987 | if (status == -NFS4ERR_DENIED) | 3006 | if (status == -NFS4ERR_DENIED) |
2988 | return decode_lock_denied(xdr, &res->u.denied); | 3007 | return decode_lock_denied(xdr, res->denied); |
2989 | return status; | 3008 | return status; |
2990 | } | 3009 | } |
2991 | 3010 | ||
2992 | static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res) | 3011 | static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) |
2993 | { | 3012 | { |
2994 | uint32_t *p; | 3013 | uint32_t *p; |
2995 | int status; | 3014 | int status; |
2996 | 3015 | ||
2997 | status = decode_op_hdr(xdr, OP_LOCKU); | 3016 | status = decode_op_hdr(xdr, OP_LOCKU); |
2998 | if (status == 0) { | 3017 | if (status == 0) { |
2999 | READ_BUF(sizeof(res->u.stateid.data)); | 3018 | READ_BUF(sizeof(res->stateid.data)); |
3000 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); | 3019 | COPYMEM(res->stateid.data, sizeof(res->stateid.data)); |
3001 | } | 3020 | } |
3002 | return status; | 3021 | return status; |
3003 | } | 3022 | } |
@@ -3861,7 +3880,7 @@ out: | |||
3861 | /* | 3880 | /* |
3862 | * Decode LOCK response | 3881 | * Decode LOCK response |
3863 | */ | 3882 | */ |
3864 | static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) | 3883 | static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lock_res *res) |
3865 | { | 3884 | { |
3866 | struct xdr_stream xdr; | 3885 | struct xdr_stream xdr; |
3867 | struct compound_hdr hdr; | 3886 | struct compound_hdr hdr; |
@@ -3882,7 +3901,7 @@ out: | |||
3882 | /* | 3901 | /* |
3883 | * Decode LOCKT response | 3902 | * Decode LOCKT response |
3884 | */ | 3903 | */ |
3885 | static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) | 3904 | static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockt_res *res) |
3886 | { | 3905 | { |
3887 | struct xdr_stream xdr; | 3906 | struct xdr_stream xdr; |
3888 | struct compound_hdr hdr; | 3907 | struct compound_hdr hdr; |
@@ -3903,7 +3922,7 @@ out: | |||
3903 | /* | 3922 | /* |
3904 | * Decode LOCKU response | 3923 | * Decode LOCKU response |
3905 | */ | 3924 | */ |
3906 | static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) | 3925 | static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_locku_res *res) |
3907 | { | 3926 | { |
3908 | struct xdr_stream xdr; | 3927 | struct xdr_stream xdr; |
3909 | struct compound_hdr hdr; | 3928 | struct compound_hdr hdr; |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 518cfa5cd024..b8b0eed98ec9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -165,50 +165,46 @@ struct nfs_closeres { | |||
165 | * * Arguments to the lock,lockt, and locku call. | 165 | * * Arguments to the lock,lockt, and locku call. |
166 | * */ | 166 | * */ |
167 | struct nfs_lowner { | 167 | struct nfs_lowner { |
168 | __u64 clientid; | 168 | __u64 clientid; |
169 | u32 id; | 169 | u32 id; |
170 | }; | 170 | }; |
171 | 171 | ||
172 | struct nfs_lock_opargs { | 172 | struct nfs_lock_args { |
173 | struct nfs_fh * fh; | ||
174 | struct file_lock * fl; | ||
173 | struct nfs_seqid * lock_seqid; | 175 | struct nfs_seqid * lock_seqid; |
174 | nfs4_stateid * lock_stateid; | 176 | nfs4_stateid * lock_stateid; |
175 | struct nfs_seqid * open_seqid; | 177 | struct nfs_seqid * open_seqid; |
176 | nfs4_stateid * open_stateid; | 178 | nfs4_stateid * open_stateid; |
177 | struct nfs_lowner lock_owner; | 179 | struct nfs_lowner lock_owner; |
178 | __u32 reclaim; | 180 | unsigned char block : 1; |
179 | __u32 new_lock_owner; | 181 | unsigned char reclaim : 1; |
182 | unsigned char new_lock_owner : 1; | ||
183 | }; | ||
184 | |||
185 | struct nfs_lock_res { | ||
186 | nfs4_stateid stateid; | ||
180 | }; | 187 | }; |
181 | 188 | ||
182 | struct nfs_locku_opargs { | 189 | struct nfs_locku_args { |
190 | struct nfs_fh * fh; | ||
191 | struct file_lock * fl; | ||
183 | struct nfs_seqid * seqid; | 192 | struct nfs_seqid * seqid; |
184 | nfs4_stateid * stateid; | 193 | nfs4_stateid * stateid; |
185 | }; | 194 | }; |
186 | 195 | ||
187 | struct nfs_lockargs { | 196 | struct nfs_locku_res { |
188 | struct nfs_fh * fh; | 197 | nfs4_stateid stateid; |
189 | __u32 type; | ||
190 | __u64 offset; | ||
191 | __u64 length; | ||
192 | union { | ||
193 | struct nfs_lock_opargs *lock; /* LOCK */ | ||
194 | struct nfs_lowner *lockt; /* LOCKT */ | ||
195 | struct nfs_locku_opargs *locku; /* LOCKU */ | ||
196 | } u; | ||
197 | }; | 198 | }; |
198 | 199 | ||
199 | struct nfs_lock_denied { | 200 | struct nfs_lockt_args { |
200 | __u64 offset; | 201 | struct nfs_fh * fh; |
201 | __u64 length; | 202 | struct file_lock * fl; |
202 | __u32 type; | 203 | struct nfs_lowner lock_owner; |
203 | struct nfs_lowner owner; | ||
204 | }; | 204 | }; |
205 | 205 | ||
206 | struct nfs_lockres { | 206 | struct nfs_lockt_res { |
207 | union { | 207 | struct file_lock * denied; /* LOCK, LOCKT failed */ |
208 | nfs4_stateid stateid;/* LOCK success, LOCKU */ | ||
209 | struct nfs_lock_denied denied; /* LOCK failed, LOCKT success */ | ||
210 | } u; | ||
211 | const struct nfs_server * server; | ||
212 | }; | 208 | }; |
213 | 209 | ||
214 | struct nfs4_delegreturnargs { | 210 | struct nfs4_delegreturnargs { |