Skip to content

Commit ea2cf22

Browse files
Fred IsamanTrond Myklebust
authored andcommitted
NFS: create struct nfs_commit_info
It is COMMIT that is handled the most differently between the paged and direct paths. Create a structure that encapsulates everything either path needs to know about the commit state. We could use void to hide some of the layout driver stuff, but Trond suggests pulling it out to ensure type checking, given the huge changes being made, and the fact that it doesn't interfere with other drivers. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
1 parent 84c53ab commit ea2cf22

File tree

8 files changed

+248
-165
lines changed

8 files changed

+248
-165
lines changed

fs/nfs/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
15471547
nfsi->delegation_state = 0;
15481548
init_rwsem(&nfsi->rwsem);
15491549
nfsi->layout = NULL;
1550-
atomic_set(&nfsi->commits_outstanding, 0);
1550+
atomic_set(&nfsi->commit_info.rpcs_out, 0);
15511551
#endif
15521552
}
15531553

@@ -1559,9 +1559,9 @@ static void init_once(void *foo)
15591559
INIT_LIST_HEAD(&nfsi->open_files);
15601560
INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
15611561
INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
1562-
INIT_LIST_HEAD(&nfsi->commit_list);
1562+
INIT_LIST_HEAD(&nfsi->commit_info.list);
15631563
nfsi->npages = 0;
1564-
nfsi->ncommit = 0;
1564+
nfsi->commit_info.ncommit = 0;
15651565
atomic_set(&nfsi->silly_count, 1);
15661566
INIT_HLIST_HEAD(&nfsi->silly_list);
15671567
init_waitqueue_head(&nfsi->waitqueue);

fs/nfs/internal.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,18 @@ extern void nfs_init_commit(struct nfs_commit_data *data,
346346
struct list_head *head,
347347
struct pnfs_layout_segment *lseg);
348348
void nfs_retry_commit(struct list_head *page_list,
349-
struct pnfs_layout_segment *lseg);
349+
struct pnfs_layout_segment *lseg,
350+
struct nfs_commit_info *cinfo);
350351
void nfs_commit_clear_lock(struct nfs_inode *nfsi);
351352
void nfs_commitdata_release(struct nfs_commit_data *data);
352353
void nfs_commit_release_pages(struct nfs_commit_data *data);
353-
void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *head);
354-
void nfs_request_remove_commit_list(struct nfs_page *req);
354+
void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
355+
struct nfs_commit_info *cinfo);
356+
void nfs_request_remove_commit_list(struct nfs_page *req,
357+
struct nfs_commit_info *cinfo);
358+
void nfs_init_cinfo(struct nfs_commit_info *cinfo,
359+
struct inode *inode,
360+
struct nfs_direct_req *dreq);
355361

356362
#ifdef CONFIG_MIGRATION
357363
extern int nfs_migrate_page(struct address_space *,

fs/nfs/nfs4filelayout.c

Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,11 @@ static void filelayout_commit_count_stats(struct rpc_task *task, void *data)
347347
static void filelayout_commit_release(void *calldata)
348348
{
349349
struct nfs_commit_data *data = calldata;
350+
struct nfs_commit_info cinfo;
350351

351352
nfs_commit_release_pages(data);
352-
if (atomic_dec_and_test(&NFS_I(data->inode)->commits_outstanding))
353+
nfs_init_cinfo(&cinfo, data->inode, data->dreq);
354+
if (atomic_dec_and_test(&cinfo.mds->rpcs_out))
353355
nfs_commit_clear_lock(NFS_I(data->inode));
354356
put_lseg(data->lseg);
355357
nfs_commitdata_release(data);
@@ -695,17 +697,16 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
695697

696698
static int
697699
filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
700+
struct nfs_commit_info *cinfo,
698701
gfp_t gfp_flags)
699702
{
700703
struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
701-
struct nfs4_filelayout *flo = FILELAYOUT_FROM_HDR(lseg->pls_layout);
702-
703-
struct nfs4_fl_commit_bucket *buckets;
704+
struct pnfs_commit_bucket *buckets;
704705
int size;
705706

706707
if (fl->commit_through_mds)
707708
return 0;
708-
if (flo->commit_info.nbuckets != 0) {
709+
if (cinfo->ds->nbuckets != 0) {
709710
/* This assumes there is only one IOMODE_RW lseg. What
710711
* we really want to do is have a layout_hdr level
711712
* dictionary of <multipath_list4, fh> keys, each
@@ -718,25 +719,25 @@ filelayout_alloc_commit_info(struct pnfs_layout_segment *lseg,
718719
size = (fl->stripe_type == STRIPE_SPARSE) ?
719720
fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
720721

721-
buckets = kcalloc(size, sizeof(struct nfs4_fl_commit_bucket),
722+
buckets = kcalloc(size, sizeof(struct pnfs_commit_bucket),
722723
gfp_flags);
723724
if (!buckets)
724725
return -ENOMEM;
725726
else {
726727
int i;
727728

728-
spin_lock(&lseg->pls_layout->plh_inode->i_lock);
729-
if (flo->commit_info.nbuckets != 0)
729+
spin_lock(cinfo->lock);
730+
if (cinfo->ds->nbuckets != 0)
730731
kfree(buckets);
731732
else {
732-
flo->commit_info.buckets = buckets;
733-
flo->commit_info.nbuckets = size;
733+
cinfo->ds->buckets = buckets;
734+
cinfo->ds->nbuckets = size;
734735
for (i = 0; i < size; i++) {
735736
INIT_LIST_HEAD(&buckets[i].written);
736737
INIT_LIST_HEAD(&buckets[i].committing);
737738
}
738739
}
739-
spin_unlock(&lseg->pls_layout->plh_inode->i_lock);
740+
spin_unlock(cinfo->lock);
740741
return 0;
741742
}
742743
}
@@ -821,6 +822,7 @@ static void
821822
filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
822823
struct nfs_page *req)
823824
{
825+
struct nfs_commit_info cinfo;
824826
int status;
825827

826828
BUG_ON(pgio->pg_lseg != NULL);
@@ -836,7 +838,8 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
836838
/* If no lseg, fall back to write through mds */
837839
if (pgio->pg_lseg == NULL)
838840
goto out_mds;
839-
status = filelayout_alloc_commit_info(pgio->pg_lseg, GFP_NOFS);
841+
nfs_init_cinfo(&cinfo, pgio->pg_inode, pgio->pg_dreq);
842+
status = filelayout_alloc_commit_info(pgio->pg_lseg, &cinfo, GFP_NOFS);
840843
if (status < 0) {
841844
put_lseg(pgio->pg_lseg);
842845
pgio->pg_lseg = NULL;
@@ -871,40 +874,42 @@ static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j)
871874
* If this will make the bucket empty, it will need to put the lseg reference.
872875
*/
873876
static void
874-
filelayout_clear_request_commit(struct nfs_page *req)
877+
filelayout_clear_request_commit(struct nfs_page *req,
878+
struct nfs_commit_info *cinfo)
875879
{
876880
struct pnfs_layout_segment *freeme = NULL;
877-
struct inode *inode = req->wb_context->dentry->d_inode;
878881

879-
spin_lock(&inode->i_lock);
882+
spin_lock(cinfo->lock);
880883
if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
881884
goto out;
885+
cinfo->ds->nwritten--;
882886
if (list_is_singular(&req->wb_list)) {
883-
struct nfs4_fl_commit_bucket *bucket;
887+
struct pnfs_commit_bucket *bucket;
884888

885889
bucket = list_first_entry(&req->wb_list,
886-
struct nfs4_fl_commit_bucket,
890+
struct pnfs_commit_bucket,
887891
written);
888892
freeme = bucket->wlseg;
889893
bucket->wlseg = NULL;
890894
}
891895
out:
892-
nfs_request_remove_commit_list(req);
893-
spin_unlock(&inode->i_lock);
896+
nfs_request_remove_commit_list(req, cinfo);
897+
spin_unlock(cinfo->lock);
894898
put_lseg(freeme);
895899
}
896900

897901
static struct list_head *
898902
filelayout_choose_commit_list(struct nfs_page *req,
899-
struct pnfs_layout_segment *lseg)
903+
struct pnfs_layout_segment *lseg,
904+
struct nfs_commit_info *cinfo)
900905
{
901906
struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
902907
u32 i, j;
903908
struct list_head *list;
904-
struct nfs4_fl_commit_bucket *buckets;
909+
struct pnfs_commit_bucket *buckets;
905910

906911
if (fl->commit_through_mds)
907-
return &NFS_I(req->wb_context->dentry->d_inode)->commit_list;
912+
return &cinfo->mds->list;
908913

909914
/* Note that we are calling nfs4_fl_calc_j_index on each page
910915
* that ends up being committed to a data server. An attractive
@@ -914,7 +919,7 @@ filelayout_choose_commit_list(struct nfs_page *req,
914919
*/
915920
j = nfs4_fl_calc_j_index(lseg, req_offset(req));
916921
i = select_bucket_index(fl, j);
917-
buckets = FILELAYOUT_FROM_HDR(lseg->pls_layout)->commit_info.buckets;
922+
buckets = cinfo->ds->buckets;
918923
list = &buckets[i].written;
919924
if (list_empty(list)) {
920925
/* Non-empty buckets hold a reference on the lseg. That ref
@@ -926,17 +931,19 @@ filelayout_choose_commit_list(struct nfs_page *req,
926931
buckets[i].wlseg = get_lseg(lseg);
927932
}
928933
set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
934+
cinfo->ds->nwritten++;
929935
return list;
930936
}
931937

932938
static void
933939
filelayout_mark_request_commit(struct nfs_page *req,
934-
struct pnfs_layout_segment *lseg)
940+
struct pnfs_layout_segment *lseg,
941+
struct nfs_commit_info *cinfo)
935942
{
936943
struct list_head *list;
937944

938-
list = filelayout_choose_commit_list(req, lseg);
939-
nfs_request_add_commit_list(req, list);
945+
list = filelayout_choose_commit_list(req, lseg, cinfo);
946+
nfs_request_add_commit_list(req, list, cinfo);
940947
}
941948

942949
static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
@@ -993,8 +1000,9 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
9931000
}
9941001

9951002
static int
996-
filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
997-
spinlock_t *lock)
1003+
filelayout_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
1004+
struct nfs_commit_info *cinfo,
1005+
int max)
9981006
{
9991007
struct list_head *src = &bucket->written;
10001008
struct list_head *dst = &bucket->committing;
@@ -1004,16 +1012,18 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
10041012
list_for_each_entry_safe(req, tmp, src, wb_list) {
10051013
if (!nfs_lock_request(req))
10061014
continue;
1007-
if (cond_resched_lock(lock))
1015+
if (cond_resched_lock(cinfo->lock))
10081016
list_safe_reset_next(req, tmp, wb_list);
1009-
nfs_request_remove_commit_list(req);
1017+
nfs_request_remove_commit_list(req, cinfo);
10101018
clear_bit(PG_COMMIT_TO_DS, &req->wb_flags);
10111019
nfs_list_add_request(req, dst);
10121020
ret++;
10131021
if (ret == max)
10141022
break;
10151023
}
10161024
if (ret) {
1025+
cinfo->ds->nwritten -= ret;
1026+
cinfo->ds->ncommitting += ret;
10171027
bucket->clseg = bucket->wlseg;
10181028
if (list_empty(src))
10191029
bucket->wlseg = NULL;
@@ -1024,37 +1034,32 @@ filelayout_scan_ds_commit_list(struct nfs4_fl_commit_bucket *bucket, int max,
10241034
}
10251035

10261036
/* Move reqs from written to committing lists, returning count of number moved.
1027-
* Note called with i_lock held.
1037+
* Note called with cinfo->lock held.
10281038
*/
1029-
static int filelayout_scan_commit_lists(struct inode *inode, int max,
1030-
spinlock_t *lock)
1039+
static int filelayout_scan_commit_lists(struct nfs_commit_info *cinfo,
1040+
int max)
10311041
{
1032-
struct nfs4_fl_commit_info *fl_cinfo;
10331042
int i, rv = 0, cnt;
10341043

1035-
fl_cinfo = &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info;
1036-
if (fl_cinfo->nbuckets == 0)
1037-
goto out_done;
1038-
for (i = 0; i < fl_cinfo->nbuckets && max != 0; i++) {
1039-
cnt = filelayout_scan_ds_commit_list(&fl_cinfo->buckets[i],
1040-
max, lock);
1044+
for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
1045+
cnt = filelayout_scan_ds_commit_list(&cinfo->ds->buckets[i],
1046+
cinfo, max);
10411047
max -= cnt;
10421048
rv += cnt;
10431049
}
1044-
out_done:
10451050
return rv;
10461051
}
10471052

10481053
static unsigned int
1049-
alloc_ds_commits(struct inode *inode, struct list_head *list)
1054+
alloc_ds_commits(struct nfs_commit_info *cinfo, struct list_head *list)
10501055
{
1051-
struct nfs4_fl_commit_info *fl_cinfo;
1052-
struct nfs4_fl_commit_bucket *bucket;
1056+
struct pnfs_ds_commit_info *fl_cinfo;
1057+
struct pnfs_commit_bucket *bucket;
10531058
struct nfs_commit_data *data;
10541059
int i, j;
10551060
unsigned int nreq = 0;
10561061

1057-
fl_cinfo = &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info;
1062+
fl_cinfo = cinfo->ds;
10581063
bucket = fl_cinfo->buckets;
10591064
for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) {
10601065
if (list_empty(&bucket->committing))
@@ -1073,7 +1078,7 @@ alloc_ds_commits(struct inode *inode, struct list_head *list)
10731078
for (j = i; j < fl_cinfo->nbuckets; j++, bucket++) {
10741079
if (list_empty(&bucket->committing))
10751080
continue;
1076-
nfs_retry_commit(&bucket->committing, bucket->clseg);
1081+
nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo);
10771082
put_lseg(bucket->clseg);
10781083
bucket->clseg = NULL;
10791084
}
@@ -1084,7 +1089,7 @@ alloc_ds_commits(struct inode *inode, struct list_head *list)
10841089
/* This follows nfs_commit_list pretty closely */
10851090
static int
10861091
filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
1087-
int how)
1092+
int how, struct nfs_commit_info *cinfo)
10881093
{
10891094
struct nfs_commit_data *data, *tmp;
10901095
LIST_HEAD(list);
@@ -1097,17 +1102,17 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
10971102
list_add(&data->pages, &list);
10981103
nreq++;
10991104
} else
1100-
nfs_retry_commit(mds_pages, NULL);
1105+
nfs_retry_commit(mds_pages, NULL, cinfo);
11011106
}
11021107

1103-
nreq += alloc_ds_commits(inode, &list);
1108+
nreq += alloc_ds_commits(cinfo, &list);
11041109

11051110
if (nreq == 0) {
11061111
nfs_commit_clear_lock(NFS_I(inode));
11071112
goto out;
11081113
}
11091114

1110-
atomic_add(nreq, &NFS_I(inode)->commits_outstanding);
1115+
atomic_add(nreq, &cinfo->mds->rpcs_out);
11111116

11121117
list_for_each_entry_safe(data, tmp, &list, pages) {
11131118
list_del_init(&data->pages);
@@ -1116,14 +1121,15 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
11161121
nfs_initiate_commit(NFS_CLIENT(inode), data,
11171122
data->mds_ops, how);
11181123
} else {
1119-
struct nfs4_fl_commit_info *fl_cinfo;
1124+
struct pnfs_commit_bucket *buckets;
11201125

1121-
fl_cinfo = &FILELAYOUT_FROM_HDR(data->lseg->pls_layout)->commit_info;
1122-
nfs_init_commit(data, &fl_cinfo->buckets[data->ds_commit_index].committing, data->lseg);
1126+
buckets = cinfo->ds->buckets;
1127+
nfs_init_commit(data, &buckets[data->ds_commit_index].committing, data->lseg);
11231128
filelayout_initiate_commit(data, how);
11241129
}
11251130
}
11261131
out:
1132+
cinfo->ds->ncommitting = 0;
11271133
return PNFS_ATTEMPTED;
11281134
}
11291135

@@ -1148,6 +1154,12 @@ filelayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
11481154
kfree(FILELAYOUT_FROM_HDR(lo));
11491155
}
11501156

1157+
static struct pnfs_ds_commit_info *
1158+
filelayout_get_ds_info(struct inode *inode)
1159+
{
1160+
return &FILELAYOUT_FROM_HDR(NFS_I(inode)->layout)->commit_info;
1161+
}
1162+
11511163
static struct pnfs_layoutdriver_type filelayout_type = {
11521164
.id = LAYOUT_NFSV4_1_FILES,
11531165
.name = "LAYOUT_NFSV4_1_FILES",
@@ -1158,6 +1170,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
11581170
.free_lseg = filelayout_free_lseg,
11591171
.pg_read_ops = &filelayout_pg_read_ops,
11601172
.pg_write_ops = &filelayout_pg_write_ops,
1173+
.get_ds_info = &filelayout_get_ds_info,
11611174
.mark_request_commit = filelayout_mark_request_commit,
11621175
.clear_request_commit = filelayout_clear_request_commit,
11631176
.scan_commit_lists = filelayout_scan_commit_lists,

fs/nfs/nfs4filelayout.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,6 @@ struct nfs4_file_layout_dsaddr {
7474
struct nfs4_pnfs_ds *ds_list[1];
7575
};
7676

77-
struct nfs4_fl_commit_bucket {
78-
struct list_head written;
79-
struct list_head committing;
80-
struct pnfs_layout_segment *wlseg;
81-
struct pnfs_layout_segment *clseg;
82-
};
83-
84-
struct nfs4_fl_commit_info {
85-
int nbuckets;
86-
struct nfs4_fl_commit_bucket *buckets;
87-
};
88-
8977
struct nfs4_filelayout_segment {
9078
struct pnfs_layout_segment generic_hdr;
9179
u32 stripe_type;
@@ -100,7 +88,7 @@ struct nfs4_filelayout_segment {
10088

10189
struct nfs4_filelayout {
10290
struct pnfs_layout_hdr generic_hdr;
103-
struct nfs4_fl_commit_info commit_info;
91+
struct pnfs_ds_commit_info commit_info;
10492
};
10593

10694
static inline struct nfs4_filelayout *

0 commit comments

Comments
 (0)