Skip to content

Commit a990189

Browse files
author
Trond Myklebust
committed
pNFS: Add infrastructure for cleaning up per-layout commit structures
Ensure that both the file and flexfiles layout types clean up when freeing the layout segments. Signed-off-by: Trond Myklebust <[email protected]>
1 parent e3b9f7e commit a990189

File tree

7 files changed

+121
-4
lines changed

7 files changed

+121
-4
lines changed

fs/nfs/filelayout/filelayout.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,16 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
750750
/* This assumes a single RW lseg */
751751
if (lseg->pls_range.iomode == IOMODE_RW) {
752752
struct nfs4_filelayout *flo;
753+
struct inode *inode;
753754

754755
flo = FILELAYOUT_FROM_HDR(lseg->pls_layout);
756+
inode = flo->generic_hdr.plh_inode;
757+
spin_lock(&inode->i_lock);
755758
flo->commit_info.nbuckets = 0;
756759
kfree(flo->commit_info.buckets);
757760
flo->commit_info.buckets = NULL;
761+
pnfs_generic_ds_cinfo_release_lseg(&flo->commit_info, lseg);
762+
spin_unlock(&inode->i_lock);
758763
}
759764
_filelayout_free_lseg(fl);
760765
}
@@ -1163,6 +1168,16 @@ filelayout_get_ds_info(struct inode *inode)
11631168
return &FILELAYOUT_FROM_HDR(layout)->commit_info;
11641169
}
11651170

1171+
static void
1172+
filelayout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
1173+
struct inode *inode)
1174+
{
1175+
spin_lock(&inode->i_lock);
1176+
pnfs_generic_ds_cinfo_destroy(fl_cinfo);
1177+
spin_unlock(&inode->i_lock);
1178+
}
1179+
1180+
11661181
static struct pnfs_layoutdriver_type filelayout_type = {
11671182
.id = LAYOUT_NFSV4_1_FILES,
11681183
.name = "LAYOUT_NFSV4_1_FILES",
@@ -1176,6 +1191,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
11761191
.pg_read_ops = &filelayout_pg_read_ops,
11771192
.pg_write_ops = &filelayout_pg_write_ops,
11781193
.get_ds_info = &filelayout_get_ds_info,
1194+
.release_ds_info = filelayout_release_ds_info,
11791195
.mark_request_commit = filelayout_mark_request_commit,
11801196
.clear_request_commit = pnfs_generic_clear_request_commit,
11811197
.scan_commit_lists = pnfs_generic_scan_commit_lists,

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ ff_layout_free_lseg(struct pnfs_layout_segment *lseg)
580580
kfree(ffl->commit_info.buckets);
581581
ffl->commit_info.buckets = NULL;
582582
}
583+
pnfs_generic_ds_cinfo_release_lseg(&ffl->commit_info, lseg);
583584
spin_unlock(&inode->i_lock);
584585
}
585586
_ff_layout_free_lseg(fls);
@@ -2003,6 +2004,15 @@ ff_layout_get_ds_info(struct inode *inode)
20032004
return &FF_LAYOUT_FROM_HDR(layout)->commit_info;
20042005
}
20052006

2007+
static void
2008+
ff_layout_release_ds_info(struct pnfs_ds_commit_info *fl_cinfo,
2009+
struct inode *inode)
2010+
{
2011+
spin_lock(&inode->i_lock);
2012+
pnfs_generic_ds_cinfo_destroy(fl_cinfo);
2013+
spin_unlock(&inode->i_lock);
2014+
}
2015+
20062016
static void
20072017
ff_layout_free_deviceid_node(struct nfs4_deviceid_node *d)
20082018
{
@@ -2503,6 +2513,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
25032513
.pg_read_ops = &ff_layout_pg_read_ops,
25042514
.pg_write_ops = &ff_layout_pg_write_ops,
25052515
.get_ds_info = ff_layout_get_ds_info,
2516+
.release_ds_info = ff_layout_release_ds_info,
25062517
.free_deviceid_node = ff_layout_free_deviceid_node,
25072518
.mark_request_commit = pnfs_layout_mark_request_commit,
25082519
.clear_request_commit = pnfs_generic_clear_request_commit,

fs/nfs/internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,11 @@ void nfs_clear_pnfs_ds_commit_verifiers(struct pnfs_ds_commit_info *cinfo)
534534
pnfs_bucket_clear_pnfs_ds_commit_verifiers(cinfo->buckets,
535535
cinfo->nbuckets);
536536

537-
list_for_each_entry(array, &cinfo->commits, cinfo_list)
537+
rcu_read_lock();
538+
list_for_each_entry_rcu(array, &cinfo->commits, cinfo_list)
538539
pnfs_bucket_clear_pnfs_ds_commit_verifiers(array->buckets,
539540
array->nbuckets);
541+
rcu_read_unlock();
540542
}
541543
#else
542544
static inline

fs/nfs/pnfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ pnfs_init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg,
506506
{
507507
INIT_LIST_HEAD(&lseg->pls_list);
508508
INIT_LIST_HEAD(&lseg->pls_lc_list);
509+
INIT_LIST_HEAD(&lseg->pls_commits);
509510
refcount_set(&lseg->pls_refcount, 1);
510511
set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
511512
lseg->pls_layout = lo;

fs/nfs/pnfs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct nfs4_pnfs_ds {
6666
struct pnfs_layout_segment {
6767
struct list_head pls_list;
6868
struct list_head pls_lc_list;
69+
struct list_head pls_commits;
6970
struct pnfs_layout_range pls_range;
7071
refcount_t pls_refcount;
7172
u32 pls_seq;
@@ -370,6 +371,9 @@ void nfs4_deviceid_purge_client(const struct nfs_client *);
370371
/* pnfs_nfs.c */
371372
struct pnfs_commit_array *pnfs_alloc_commit_array(size_t n, gfp_t gfp_flags);
372373
void pnfs_free_commit_array(struct pnfs_commit_array *p);
374+
void pnfs_generic_ds_cinfo_release_lseg(struct pnfs_ds_commit_info *fl_cinfo,
375+
struct pnfs_layout_segment *lseg);
376+
void pnfs_generic_ds_cinfo_destroy(struct pnfs_ds_commit_info *fl_cinfo);
373377

374378
void pnfs_generic_clear_request_commit(struct nfs_page *req,
375379
struct nfs_commit_info *cinfo);

fs/nfs/pnfs_nfs.c

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,67 @@ pnfs_free_commit_array(struct pnfs_commit_array *p)
118118
}
119119
EXPORT_SYMBOL_GPL(pnfs_free_commit_array);
120120

121+
static void
122+
pnfs_release_commit_array_locked(struct pnfs_commit_array *array)
123+
{
124+
list_del_rcu(&array->cinfo_list);
125+
list_del(&array->lseg_list);
126+
pnfs_free_commit_array(array);
127+
}
128+
129+
static void
130+
pnfs_put_commit_array_locked(struct pnfs_commit_array *array)
131+
{
132+
if (refcount_dec_and_test(&array->refcount))
133+
pnfs_release_commit_array_locked(array);
134+
}
135+
136+
static void
137+
pnfs_put_commit_array(struct pnfs_commit_array *array, struct inode *inode)
138+
{
139+
if (refcount_dec_and_lock(&array->refcount, &inode->i_lock)) {
140+
pnfs_release_commit_array_locked(array);
141+
spin_unlock(&inode->i_lock);
142+
}
143+
}
144+
145+
static struct pnfs_commit_array *
146+
pnfs_get_commit_array(struct pnfs_commit_array *array)
147+
{
148+
if (refcount_inc_not_zero(&array->refcount))
149+
return array;
150+
return NULL;
151+
}
152+
153+
static void
154+
pnfs_remove_and_free_commit_array(struct pnfs_commit_array *array)
155+
{
156+
array->lseg = NULL;
157+
list_del_init(&array->lseg_list);
158+
pnfs_put_commit_array_locked(array);
159+
}
160+
161+
void
162+
pnfs_generic_ds_cinfo_release_lseg(struct pnfs_ds_commit_info *fl_cinfo,
163+
struct pnfs_layout_segment *lseg)
164+
{
165+
struct pnfs_commit_array *array, *tmp;
166+
167+
list_for_each_entry_safe(array, tmp, &lseg->pls_commits, lseg_list)
168+
pnfs_remove_and_free_commit_array(array);
169+
}
170+
EXPORT_SYMBOL_GPL(pnfs_generic_ds_cinfo_release_lseg);
171+
172+
void
173+
pnfs_generic_ds_cinfo_destroy(struct pnfs_ds_commit_info *fl_cinfo)
174+
{
175+
struct pnfs_commit_array *array, *tmp;
176+
177+
list_for_each_entry_safe(array, tmp, &fl_cinfo->commits, cinfo_list)
178+
pnfs_remove_and_free_commit_array(array);
179+
}
180+
EXPORT_SYMBOL_GPL(pnfs_generic_ds_cinfo_destroy);
181+
121182
/*
122183
* Locks the nfs_page requests for commit and moves them to
123184
* @bucket->committing.
@@ -177,14 +238,21 @@ int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max)
177238
max -= cnt;
178239
if (!max)
179240
return rv;
180-
list_for_each_entry(array, &fl_cinfo->commits, cinfo_list) {
241+
rcu_read_lock();
242+
list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
243+
if (!array->lseg || !pnfs_get_commit_array(array))
244+
continue;
245+
rcu_read_unlock();
181246
cnt = pnfs_bucket_scan_array(cinfo, array->buckets,
182247
array->nbuckets, max);
248+
rcu_read_lock();
249+
pnfs_put_commit_array(array, cinfo->inode);
183250
rv += cnt;
184251
max -= cnt;
185252
if (!max)
186253
break;
187254
}
255+
rcu_read_unlock();
188256
return rv;
189257
}
190258
EXPORT_SYMBOL_GPL(pnfs_generic_scan_commit_lists);
@@ -230,13 +298,20 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
230298
fl_cinfo->nbuckets,
231299
cinfo);
232300
fl_cinfo->nwritten -= nwritten;
233-
list_for_each_entry(array, &fl_cinfo->commits, cinfo_list) {
301+
rcu_read_lock();
302+
list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
303+
if (!array->lseg || !pnfs_get_commit_array(array))
304+
continue;
305+
rcu_read_unlock();
234306
nwritten = pnfs_bucket_recover_commit_reqs(dst,
235307
array->buckets,
236308
array->nbuckets,
237309
cinfo);
310+
rcu_read_lock();
311+
pnfs_put_commit_array(array, cinfo->inode);
238312
fl_cinfo->nwritten -= nwritten;
239313
}
314+
rcu_read_unlock();
240315
}
241316
EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs);
242317

@@ -330,9 +405,16 @@ pnfs_alloc_ds_commits_list(struct list_head *list,
330405
struct pnfs_commit_array *array;
331406
unsigned int ret = 0;
332407

333-
list_for_each_entry(array, &fl_cinfo->commits, cinfo_list)
408+
rcu_read_lock();
409+
list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
410+
if (!array->lseg || !pnfs_get_commit_array(array))
411+
continue;
412+
rcu_read_unlock();
334413
ret += pnfs_bucket_alloc_ds_commits(list, array->buckets,
335414
array->nbuckets, cinfo);
415+
rcu_read_lock();
416+
pnfs_put_commit_array(array, cinfo->inode);
417+
}
336418
return ret;
337419
}
338420

include/linux/nfs_xdr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,7 @@ struct pnfs_commit_array {
12751275
struct list_head lseg_list;
12761276
struct pnfs_layout_segment *lseg;
12771277
struct rcu_head rcu;
1278+
refcount_t refcount;
12781279
unsigned int nbuckets;
12791280
struct pnfs_commit_bucket buckets[];
12801281
};

0 commit comments

Comments
 (0)