diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-06-25 16:35:53 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-30 14:41:56 -0400 |
commit | f11ac8db5d07b6e99d41ff4aa39d878ee5cef1c5 (patch) | |
tree | 4393cbc2653145ba3269d5143f5db7811a59698b | |
parent | 1f0e890dba5b0f543fea47732116b1c65d55614e (diff) |
NFSv4: Ensure that we track the NFSv4 lock state in read/write requests.
This patch fixes bugzilla entry 14501:
https://bugzilla.kernel.org/show_bug.cgi?id=14501
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/direct.c | 29 | ||||
-rw-r--r-- | fs/nfs/inode.c | 70 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 8 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 8 | ||||
-rw-r--r-- | fs/nfs/read.c | 1 | ||||
-rw-r--r-- | fs/nfs/write.c | 5 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 13 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
9 files changed, 118 insertions, 19 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index ad4cd31d6050..064a80961677 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -69,6 +69,7 @@ struct nfs_direct_req { | |||
69 | 69 | ||
70 | /* I/O parameters */ | 70 | /* I/O parameters */ |
71 | struct nfs_open_context *ctx; /* file open context info */ | 71 | struct nfs_open_context *ctx; /* file open context info */ |
72 | struct nfs_lock_context *l_ctx; /* Lock context info */ | ||
72 | struct kiocb * iocb; /* controlling i/o request */ | 73 | struct kiocb * iocb; /* controlling i/o request */ |
73 | struct inode * inode; /* target file of i/o */ | 74 | struct inode * inode; /* target file of i/o */ |
74 | 75 | ||
@@ -160,6 +161,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void) | |||
160 | INIT_LIST_HEAD(&dreq->rewrite_list); | 161 | INIT_LIST_HEAD(&dreq->rewrite_list); |
161 | dreq->iocb = NULL; | 162 | dreq->iocb = NULL; |
162 | dreq->ctx = NULL; | 163 | dreq->ctx = NULL; |
164 | dreq->l_ctx = NULL; | ||
163 | spin_lock_init(&dreq->lock); | 165 | spin_lock_init(&dreq->lock); |
164 | atomic_set(&dreq->io_count, 0); | 166 | atomic_set(&dreq->io_count, 0); |
165 | dreq->count = 0; | 167 | dreq->count = 0; |
@@ -173,6 +175,8 @@ static void nfs_direct_req_free(struct kref *kref) | |||
173 | { | 175 | { |
174 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); | 176 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); |
175 | 177 | ||
178 | if (dreq->l_ctx != NULL) | ||
179 | nfs_put_lock_context(dreq->l_ctx); | ||
176 | if (dreq->ctx != NULL) | 180 | if (dreq->ctx != NULL) |
177 | put_nfs_open_context(dreq->ctx); | 181 | put_nfs_open_context(dreq->ctx); |
178 | kmem_cache_free(nfs_direct_cachep, dreq); | 182 | kmem_cache_free(nfs_direct_cachep, dreq); |
@@ -336,6 +340,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
336 | data->cred = msg.rpc_cred; | 340 | data->cred = msg.rpc_cred; |
337 | data->args.fh = NFS_FH(inode); | 341 | data->args.fh = NFS_FH(inode); |
338 | data->args.context = ctx; | 342 | data->args.context = ctx; |
343 | data->args.lock_context = dreq->l_ctx; | ||
339 | data->args.offset = pos; | 344 | data->args.offset = pos; |
340 | data->args.pgbase = pgbase; | 345 | data->args.pgbase = pgbase; |
341 | data->args.pages = data->pagevec; | 346 | data->args.pages = data->pagevec; |
@@ -416,24 +421,28 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
416 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | 421 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
417 | unsigned long nr_segs, loff_t pos) | 422 | unsigned long nr_segs, loff_t pos) |
418 | { | 423 | { |
419 | ssize_t result = 0; | 424 | ssize_t result = -ENOMEM; |
420 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 425 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
421 | struct nfs_direct_req *dreq; | 426 | struct nfs_direct_req *dreq; |
422 | 427 | ||
423 | dreq = nfs_direct_req_alloc(); | 428 | dreq = nfs_direct_req_alloc(); |
424 | if (!dreq) | 429 | if (dreq == NULL) |
425 | return -ENOMEM; | 430 | goto out; |
426 | 431 | ||
427 | dreq->inode = inode; | 432 | dreq->inode = inode; |
428 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 433 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
434 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | ||
435 | if (dreq->l_ctx == NULL) | ||
436 | goto out_release; | ||
429 | if (!is_sync_kiocb(iocb)) | 437 | if (!is_sync_kiocb(iocb)) |
430 | dreq->iocb = iocb; | 438 | dreq->iocb = iocb; |
431 | 439 | ||
432 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); | 440 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
433 | if (!result) | 441 | if (!result) |
434 | result = nfs_direct_wait(dreq); | 442 | result = nfs_direct_wait(dreq); |
443 | out_release: | ||
435 | nfs_direct_req_release(dreq); | 444 | nfs_direct_req_release(dreq); |
436 | 445 | out: | |
437 | return result; | 446 | return result; |
438 | } | 447 | } |
439 | 448 | ||
@@ -574,6 +583,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
574 | data->args.offset = 0; | 583 | data->args.offset = 0; |
575 | data->args.count = 0; | 584 | data->args.count = 0; |
576 | data->args.context = dreq->ctx; | 585 | data->args.context = dreq->ctx; |
586 | data->args.lock_context = dreq->l_ctx; | ||
577 | data->res.count = 0; | 587 | data->res.count = 0; |
578 | data->res.fattr = &data->fattr; | 588 | data->res.fattr = &data->fattr; |
579 | data->res.verf = &data->verf; | 589 | data->res.verf = &data->verf; |
@@ -761,6 +771,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
761 | data->cred = msg.rpc_cred; | 771 | data->cred = msg.rpc_cred; |
762 | data->args.fh = NFS_FH(inode); | 772 | data->args.fh = NFS_FH(inode); |
763 | data->args.context = ctx; | 773 | data->args.context = ctx; |
774 | data->args.lock_context = dreq->l_ctx; | ||
764 | data->args.offset = pos; | 775 | data->args.offset = pos; |
765 | data->args.pgbase = pgbase; | 776 | data->args.pgbase = pgbase; |
766 | data->args.pages = data->pagevec; | 777 | data->args.pages = data->pagevec; |
@@ -845,7 +856,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
845 | unsigned long nr_segs, loff_t pos, | 856 | unsigned long nr_segs, loff_t pos, |
846 | size_t count) | 857 | size_t count) |
847 | { | 858 | { |
848 | ssize_t result = 0; | 859 | ssize_t result = -ENOMEM; |
849 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 860 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
850 | struct nfs_direct_req *dreq; | 861 | struct nfs_direct_req *dreq; |
851 | size_t wsize = NFS_SERVER(inode)->wsize; | 862 | size_t wsize = NFS_SERVER(inode)->wsize; |
@@ -853,7 +864,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
853 | 864 | ||
854 | dreq = nfs_direct_req_alloc(); | 865 | dreq = nfs_direct_req_alloc(); |
855 | if (!dreq) | 866 | if (!dreq) |
856 | return -ENOMEM; | 867 | goto out; |
857 | nfs_alloc_commit_data(dreq); | 868 | nfs_alloc_commit_data(dreq); |
858 | 869 | ||
859 | if (dreq->commit_data == NULL || count < wsize) | 870 | if (dreq->commit_data == NULL || count < wsize) |
@@ -861,14 +872,18 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
861 | 872 | ||
862 | dreq->inode = inode; | 873 | dreq->inode = inode; |
863 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 874 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
875 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | ||
876 | if (dreq->l_ctx != NULL) | ||
877 | goto out_release; | ||
864 | if (!is_sync_kiocb(iocb)) | 878 | if (!is_sync_kiocb(iocb)) |
865 | dreq->iocb = iocb; | 879 | dreq->iocb = iocb; |
866 | 880 | ||
867 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); | 881 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
868 | if (!result) | 882 | if (!result) |
869 | result = nfs_direct_wait(dreq); | 883 | result = nfs_direct_wait(dreq); |
884 | out_release: | ||
870 | nfs_direct_req_release(dreq); | 885 | nfs_direct_req_release(dreq); |
871 | 886 | out: | |
872 | return result; | 887 | return result; |
873 | } | 888 | } |
874 | 889 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 099b3518feea..ec7a8f96a2c2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -530,6 +530,68 @@ out: | |||
530 | return err; | 530 | return err; |
531 | } | 531 | } |
532 | 532 | ||
533 | static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) | ||
534 | { | ||
535 | atomic_set(&l_ctx->count, 1); | ||
536 | l_ctx->lockowner = current->files; | ||
537 | l_ctx->pid = current->tgid; | ||
538 | INIT_LIST_HEAD(&l_ctx->list); | ||
539 | } | ||
540 | |||
541 | static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) | ||
542 | { | ||
543 | struct nfs_lock_context *pos; | ||
544 | |||
545 | list_for_each_entry(pos, &ctx->lock_context.list, list) { | ||
546 | if (pos->lockowner != current->files) | ||
547 | continue; | ||
548 | if (pos->pid != current->tgid) | ||
549 | continue; | ||
550 | atomic_inc(&pos->count); | ||
551 | return pos; | ||
552 | } | ||
553 | return NULL; | ||
554 | } | ||
555 | |||
556 | struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx) | ||
557 | { | ||
558 | struct nfs_lock_context *res, *new = NULL; | ||
559 | struct inode *inode = ctx->path.dentry->d_inode; | ||
560 | |||
561 | spin_lock(&inode->i_lock); | ||
562 | res = __nfs_find_lock_context(ctx); | ||
563 | if (res == NULL) { | ||
564 | spin_unlock(&inode->i_lock); | ||
565 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
566 | if (new == NULL) | ||
567 | return NULL; | ||
568 | nfs_init_lock_context(new); | ||
569 | spin_lock(&inode->i_lock); | ||
570 | res = __nfs_find_lock_context(ctx); | ||
571 | if (res == NULL) { | ||
572 | list_add_tail(&new->list, &ctx->lock_context.list); | ||
573 | new->open_context = ctx; | ||
574 | res = new; | ||
575 | new = NULL; | ||
576 | } | ||
577 | } | ||
578 | spin_unlock(&inode->i_lock); | ||
579 | kfree(new); | ||
580 | return res; | ||
581 | } | ||
582 | |||
583 | void nfs_put_lock_context(struct nfs_lock_context *l_ctx) | ||
584 | { | ||
585 | struct nfs_open_context *ctx = l_ctx->open_context; | ||
586 | struct inode *inode = ctx->path.dentry->d_inode; | ||
587 | |||
588 | if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock)) | ||
589 | return; | ||
590 | list_del(&l_ctx->list); | ||
591 | spin_unlock(&inode->i_lock); | ||
592 | kfree(l_ctx); | ||
593 | } | ||
594 | |||
533 | /** | 595 | /** |
534 | * nfs_close_context - Common close_context() routine NFSv2/v3 | 596 | * nfs_close_context - Common close_context() routine NFSv2/v3 |
535 | * @ctx: pointer to context | 597 | * @ctx: pointer to context |
@@ -566,11 +628,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
566 | path_get(&ctx->path); | 628 | path_get(&ctx->path); |
567 | ctx->cred = get_rpccred(cred); | 629 | ctx->cred = get_rpccred(cred); |
568 | ctx->state = NULL; | 630 | ctx->state = NULL; |
569 | ctx->lockowner = current->files; | ||
570 | ctx->flags = 0; | 631 | ctx->flags = 0; |
571 | ctx->error = 0; | 632 | ctx->error = 0; |
572 | ctx->dir_cookie = 0; | 633 | ctx->dir_cookie = 0; |
573 | atomic_set(&ctx->count, 1); | 634 | nfs_init_lock_context(&ctx->lock_context); |
635 | ctx->lock_context.open_context = ctx; | ||
574 | } | 636 | } |
575 | return ctx; | 637 | return ctx; |
576 | } | 638 | } |
@@ -578,7 +640,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
578 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | 640 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) |
579 | { | 641 | { |
580 | if (ctx != NULL) | 642 | if (ctx != NULL) |
581 | atomic_inc(&ctx->count); | 643 | atomic_inc(&ctx->lock_context.count); |
582 | return ctx; | 644 | return ctx; |
583 | } | 645 | } |
584 | 646 | ||
@@ -586,7 +648,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
586 | { | 648 | { |
587 | struct inode *inode = ctx->path.dentry->d_inode; | 649 | struct inode *inode = ctx->path.dentry->d_inode; |
588 | 650 | ||
589 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 651 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) |
590 | return; | 652 | return; |
591 | list_del(&ctx->list); | 653 | list_del(&ctx->list); |
592 | spin_unlock(&inode->i_lock); | 654 | spin_unlock(&inode->i_lock); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1f7781d636ae..873b62f209ea 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1324,14 +1324,14 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) | |||
1324 | hdr->replen += decode_putrootfh_maxsz; | 1324 | hdr->replen += decode_putrootfh_maxsz; |
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) | 1327 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx) |
1328 | { | 1328 | { |
1329 | nfs4_stateid stateid; | 1329 | nfs4_stateid stateid; |
1330 | __be32 *p; | 1330 | __be32 *p; |
1331 | 1331 | ||
1332 | p = reserve_space(xdr, NFS4_STATEID_SIZE); | 1332 | p = reserve_space(xdr, NFS4_STATEID_SIZE); |
1333 | if (ctx->state != NULL) { | 1333 | if (ctx->state != NULL) { |
1334 | nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner); | 1334 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner); |
1335 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); | 1335 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); |
1336 | } else | 1336 | } else |
1337 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); | 1337 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); |
@@ -1344,7 +1344,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1344 | p = reserve_space(xdr, 4); | 1344 | p = reserve_space(xdr, 4); |
1345 | *p = cpu_to_be32(OP_READ); | 1345 | *p = cpu_to_be32(OP_READ); |
1346 | 1346 | ||
1347 | encode_stateid(xdr, args->context); | 1347 | encode_stateid(xdr, args->context, args->lock_context); |
1348 | 1348 | ||
1349 | p = reserve_space(xdr, 12); | 1349 | p = reserve_space(xdr, 12); |
1350 | p = xdr_encode_hyper(p, args->offset); | 1350 | p = xdr_encode_hyper(p, args->offset); |
@@ -1523,7 +1523,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg | |||
1523 | p = reserve_space(xdr, 4); | 1523 | p = reserve_space(xdr, 4); |
1524 | *p = cpu_to_be32(OP_WRITE); | 1524 | *p = cpu_to_be32(OP_WRITE); |
1525 | 1525 | ||
1526 | encode_stateid(xdr, args->context); | 1526 | encode_stateid(xdr, args->context, args->lock_context); |
1527 | 1527 | ||
1528 | p = reserve_space(xdr, 16); | 1528 | p = reserve_space(xdr, 16); |
1529 | p = xdr_encode_hyper(p, args->offset); | 1529 | p = xdr_encode_hyper(p, args->offset); |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index a3654e57b589..919490232e17 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -79,6 +79,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
79 | req->wb_pgbase = offset; | 79 | req->wb_pgbase = offset; |
80 | req->wb_bytes = count; | 80 | req->wb_bytes = count; |
81 | req->wb_context = get_nfs_open_context(ctx); | 81 | req->wb_context = get_nfs_open_context(ctx); |
82 | req->wb_lock_context = nfs_get_lock_context(ctx); | ||
82 | kref_init(&req->wb_kref); | 83 | kref_init(&req->wb_kref); |
83 | return req; | 84 | return req; |
84 | } | 85 | } |
@@ -141,11 +142,16 @@ void nfs_clear_request(struct nfs_page *req) | |||
141 | { | 142 | { |
142 | struct page *page = req->wb_page; | 143 | struct page *page = req->wb_page; |
143 | struct nfs_open_context *ctx = req->wb_context; | 144 | struct nfs_open_context *ctx = req->wb_context; |
145 | struct nfs_lock_context *l_ctx = req->wb_lock_context; | ||
144 | 146 | ||
145 | if (page != NULL) { | 147 | if (page != NULL) { |
146 | page_cache_release(page); | 148 | page_cache_release(page); |
147 | req->wb_page = NULL; | 149 | req->wb_page = NULL; |
148 | } | 150 | } |
151 | if (l_ctx != NULL) { | ||
152 | nfs_put_lock_context(l_ctx); | ||
153 | req->wb_lock_context = NULL; | ||
154 | } | ||
149 | if (ctx != NULL) { | 155 | if (ctx != NULL) { |
150 | put_nfs_open_context(ctx); | 156 | put_nfs_open_context(ctx); |
151 | req->wb_context = NULL; | 157 | req->wb_context = NULL; |
@@ -235,7 +241,7 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev, | |||
235 | { | 241 | { |
236 | if (req->wb_context->cred != prev->wb_context->cred) | 242 | if (req->wb_context->cred != prev->wb_context->cred) |
237 | return 0; | 243 | return 0; |
238 | if (req->wb_context->lockowner != prev->wb_context->lockowner) | 244 | if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner) |
239 | return 0; | 245 | return 0; |
240 | if (req->wb_context->state != prev->wb_context->state) | 246 | if (req->wb_context->state != prev->wb_context->state) |
241 | return 0; | 247 | return 0; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 5a33a92e8168..87adc2744246 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -190,6 +190,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
190 | data->args.pages = data->pagevec; | 190 | data->args.pages = data->pagevec; |
191 | data->args.count = count; | 191 | data->args.count = count; |
192 | data->args.context = get_nfs_open_context(req->wb_context); | 192 | data->args.context = get_nfs_open_context(req->wb_context); |
193 | data->args.lock_context = req->wb_lock_context; | ||
193 | 194 | ||
194 | data->res.fattr = &data->fattr; | 195 | data->res.fattr = &data->fattr; |
195 | data->res.count = count; | 196 | data->res.count = count; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 03df22822c4c..5eccea127cac 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -689,7 +689,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
689 | req = nfs_page_find_request(page); | 689 | req = nfs_page_find_request(page); |
690 | if (req == NULL) | 690 | if (req == NULL) |
691 | return 0; | 691 | return 0; |
692 | do_flush = req->wb_page != page || req->wb_context != ctx; | 692 | do_flush = req->wb_page != page || req->wb_context != ctx || |
693 | req->wb_lock_context->lockowner != current->files || | ||
694 | req->wb_lock_context->pid != current->tgid; | ||
693 | nfs_release_request(req); | 695 | nfs_release_request(req); |
694 | if (!do_flush) | 696 | if (!do_flush) |
695 | return 0; | 697 | return 0; |
@@ -813,6 +815,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
813 | data->args.pages = data->pagevec; | 815 | data->args.pages = data->pagevec; |
814 | data->args.count = count; | 816 | data->args.count = count; |
815 | data->args.context = get_nfs_open_context(req->wb_context); | 817 | data->args.context = get_nfs_open_context(req->wb_context); |
818 | data->args.lock_context = req->wb_lock_context; | ||
816 | data->args.stable = NFS_UNSTABLE; | 819 | data->args.stable = NFS_UNSTABLE; |
817 | if (how & FLUSH_STABLE) { | 820 | if (how & FLUSH_STABLE) { |
818 | data->args.stable = NFS_DATA_SYNC; | 821 | data->args.stable = NFS_DATA_SYNC; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 77c2ae53431c..a9d802615082 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -72,13 +72,20 @@ struct nfs_access_entry { | |||
72 | int mask; | 72 | int mask; |
73 | }; | 73 | }; |
74 | 74 | ||
75 | struct nfs_lock_context { | ||
76 | atomic_t count; | ||
77 | struct list_head list; | ||
78 | struct nfs_open_context *open_context; | ||
79 | fl_owner_t lockowner; | ||
80 | pid_t pid; | ||
81 | }; | ||
82 | |||
75 | struct nfs4_state; | 83 | struct nfs4_state; |
76 | struct nfs_open_context { | 84 | struct nfs_open_context { |
77 | atomic_t count; | 85 | struct nfs_lock_context lock_context; |
78 | struct path path; | 86 | struct path path; |
79 | struct rpc_cred *cred; | 87 | struct rpc_cred *cred; |
80 | struct nfs4_state *state; | 88 | struct nfs4_state *state; |
81 | fl_owner_t lockowner; | ||
82 | fmode_t mode; | 89 | fmode_t mode; |
83 | 90 | ||
84 | unsigned long flags; | 91 | unsigned long flags; |
@@ -353,6 +360,8 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | |||
353 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 360 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
354 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 361 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
355 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); | 362 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); |
363 | extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx); | ||
364 | extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx); | ||
356 | extern u64 nfs_compat_user_ino64(u64 fileid); | 365 | extern u64 nfs_compat_user_ino64(u64 fileid); |
357 | extern void nfs_fattr_init(struct nfs_fattr *fattr); | 366 | extern void nfs_fattr_init(struct nfs_fattr *fattr); |
358 | 367 | ||
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 3c60685d972b..f8b60e7f4c44 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -39,6 +39,7 @@ struct nfs_page { | |||
39 | struct list_head wb_list; /* Defines state of page: */ | 39 | struct list_head wb_list; /* Defines state of page: */ |
40 | struct page *wb_page; /* page to read in/write out */ | 40 | struct page *wb_page; /* page to read in/write out */ |
41 | struct nfs_open_context *wb_context; /* File state context info */ | 41 | struct nfs_open_context *wb_context; /* File state context info */ |
42 | struct nfs_lock_context *wb_lock_context; /* lock context info */ | ||
42 | atomic_t wb_complete; /* i/os we're waiting for */ | 43 | atomic_t wb_complete; /* i/os we're waiting for */ |
43 | pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */ | 44 | pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */ |
44 | unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */ | 45 | unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */ |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index a319cb926abf..87202c7026e3 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -334,6 +334,7 @@ struct nfs4_delegreturnres { | |||
334 | struct nfs_readargs { | 334 | struct nfs_readargs { |
335 | struct nfs_fh * fh; | 335 | struct nfs_fh * fh; |
336 | struct nfs_open_context *context; | 336 | struct nfs_open_context *context; |
337 | struct nfs_lock_context *lock_context; | ||
337 | __u64 offset; | 338 | __u64 offset; |
338 | __u32 count; | 339 | __u32 count; |
339 | unsigned int pgbase; | 340 | unsigned int pgbase; |
@@ -354,6 +355,7 @@ struct nfs_readres { | |||
354 | struct nfs_writeargs { | 355 | struct nfs_writeargs { |
355 | struct nfs_fh * fh; | 356 | struct nfs_fh * fh; |
356 | struct nfs_open_context *context; | 357 | struct nfs_open_context *context; |
358 | struct nfs_lock_context *lock_context; | ||
357 | __u64 offset; | 359 | __u64 offset; |
358 | __u32 count; | 360 | __u32 count; |
359 | enum nfs3_stable_how stable; | 361 | enum nfs3_stable_how stable; |