diff options
Diffstat (limited to 'fs/nfs/direct.c')
| -rw-r--r-- | fs/nfs/direct.c | 29 |
1 files changed, 22 insertions, 7 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 | ||
