@@ -118,6 +118,67 @@ pnfs_free_commit_array(struct pnfs_commit_array *p)
118118}
119119EXPORT_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}
190258EXPORT_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}
241316EXPORT_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
0 commit comments