aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c192
-rw-r--r--fs/nfs/nfs4xdr.c131
-rw-r--r--include/linux/nfs_xdr.h52
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
2938static inline int
2939nfs4_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
2954static inline uint64_t
2955nfs4_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
2962static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request) 2938static 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 }
3013out: 2974out:
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
3050struct nfs4_unlockdata { 3011struct 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
3020static 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
3058static void nfs4_locku_release_calldata(void *data) 3044static 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 }
3169out: 3142 return status;
3143out_free_seqid:
3144 nfs_free_seqid(seqid);
3145out_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;
3237out: 3205out:
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
745static 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
752static 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 */
749static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) 763static 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
779static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockargs *arg) 792static 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
796static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) 808static 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 */
1599static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) 1610static 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 */
1627static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) 1637static 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 */
1648static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) 1658static 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 */
2952static int decode_lock_denied (struct xdr_stream *xdr, struct nfs_lock_denied *denied) 2962static 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
2969static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res) 2988static 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
2983static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockres *res) 3002static 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
2992static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res) 3011static 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 */
3864static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) 3883static 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 */
3885static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) 3904static 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 */
3906static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) 3925static 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 * */
167struct nfs_lowner { 167struct nfs_lowner {
168 __u64 clientid; 168 __u64 clientid;
169 u32 id; 169 u32 id;
170}; 170};
171 171
172struct nfs_lock_opargs { 172struct 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
185struct nfs_lock_res {
186 nfs4_stateid stateid;
180}; 187};
181 188
182struct nfs_locku_opargs { 189struct 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
187struct nfs_lockargs { 196struct 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
199struct nfs_lock_denied { 200struct 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
206struct nfs_lockres { 206struct 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
214struct nfs4_delegreturnargs { 210struct nfs4_delegreturnargs {