@@ -93,12 +93,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
9393 _enter (",,%s" , dirname );
9494
9595 /* search the current directory for the element name */
96- inode_lock_nested (d_inode (dir ), I_MUTEX_PARENT );
9796
9897retry :
9998 ret = cachefiles_inject_read_error ();
10099 if (ret == 0 )
101- subdir = lookup_one (& nop_mnt_idmap , & QSTR (dirname ), dir );
100+ subdir = start_creating (& nop_mnt_idmap , dir , & QSTR (dirname ));
102101 else
103102 subdir = ERR_PTR (ret );
104103 trace_cachefiles_lookup (NULL , dir , subdir );
@@ -129,10 +128,12 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
129128 if (ret < 0 )
130129 goto mkdir_error ;
131130 ret = cachefiles_inject_write_error ();
132- if (ret == 0 )
131+ if (ret == 0 ) {
133132 subdir = vfs_mkdir (& nop_mnt_idmap , d_inode (dir ), subdir , 0700 );
134- else
133+ } else {
134+ end_creating (subdir );
135135 subdir = ERR_PTR (ret );
136+ }
136137 if (IS_ERR (subdir )) {
137138 trace_cachefiles_vfs_error (NULL , d_inode (dir ), ret ,
138139 cachefiles_trace_mkdir_error );
@@ -141,7 +142,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
141142 trace_cachefiles_mkdir (dir , subdir );
142143
143144 if (unlikely (d_unhashed (subdir ) || d_is_negative (subdir ))) {
144- dput (subdir );
145+ end_creating (subdir );
145146 goto retry ;
146147 }
147148 ASSERT (d_backing_inode (subdir ));
@@ -154,7 +155,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
154155
155156 /* Tell rmdir() it's not allowed to delete the subdir */
156157 inode_lock (d_inode (subdir ));
157- inode_unlock ( d_inode ( dir ) );
158+ end_creating_keep ( subdir );
158159
159160 if (!__cachefiles_mark_inode_in_use (NULL , d_inode (subdir ))) {
160161 pr_notice ("cachefiles: Inode already in use: %pd (B=%lx)\n" ,
@@ -196,14 +197,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
196197 return ERR_PTR (- EBUSY );
197198
198199mkdir_error :
199- inode_unlock (d_inode (dir ));
200- if (!IS_ERR (subdir ))
201- dput (subdir );
200+ end_creating (subdir );
202201 pr_err ("mkdir %s failed with error %d\n" , dirname , ret );
203202 return ERR_PTR (ret );
204203
205204lookup_error :
206- inode_unlock (d_inode (dir ));
207205 ret = PTR_ERR (subdir );
208206 pr_err ("Lookup %s failed with error %d\n" , dirname , ret );
209207 return ERR_PTR (ret );
@@ -263,6 +261,8 @@ static int cachefiles_unlink(struct cachefiles_cache *cache,
263261 * - File backed objects are unlinked
264262 * - Directory backed objects are stuffed into the graveyard for userspace to
265263 * delete
264+ * On entry dir must be locked. It will be unlocked on exit.
265+ * On entry there must be at least 2 refs on rep, one will be dropped on exit.
266266 */
267267int cachefiles_bury_object (struct cachefiles_cache * cache ,
268268 struct cachefiles_object * object ,
@@ -278,27 +278,23 @@ int cachefiles_bury_object(struct cachefiles_cache *cache,
278278 _enter (",'%pd','%pd'" , dir , rep );
279279
280280 if (rep -> d_parent != dir ) {
281- inode_unlock ( d_inode ( dir ) );
281+ end_removing ( rep );
282282 _leave (" = -ESTALE" );
283283 return - ESTALE ;
284284 }
285285
286286 /* non-directories can just be unlinked */
287287 if (!d_is_dir (rep )) {
288- dget (rep ); /* Stop the dentry being negated if it's only pinned
289- * by a file struct.
290- */
291288 ret = cachefiles_unlink (cache , object , dir , rep , why );
292- dput (rep );
289+ end_removing (rep );
293290
294- inode_unlock (d_inode (dir ));
295291 _leave (" = %d" , ret );
296292 return ret ;
297293 }
298294
299295 /* directories have to be moved to the graveyard */
300296 _debug ("move stale object to graveyard" );
301- inode_unlock ( d_inode ( dir ) );
297+ end_removing ( rep );
302298
303299try_again :
304300 /* first step is to make up a grave dentry in the graveyard */
@@ -425,13 +421,12 @@ int cachefiles_delete_object(struct cachefiles_object *object,
425421
426422 _enter (",OBJ%x{%pD}" , object -> debug_id , object -> file );
427423
428- /* Stop the dentry being negated if it's only pinned by a file struct. */
429- dget (dentry );
430-
431- inode_lock_nested (d_backing_inode (fan ), I_MUTEX_PARENT );
432- ret = cachefiles_unlink (volume -> cache , object , fan , dentry , why );
433- inode_unlock (d_backing_inode (fan ));
434- dput (dentry );
424+ dentry = start_removing_dentry (fan , dentry );
425+ if (IS_ERR (dentry ))
426+ ret = PTR_ERR (dentry );
427+ else
428+ ret = cachefiles_unlink (volume -> cache , object , fan , dentry , why );
429+ end_removing (dentry );
435430 return ret ;
436431}
437432
@@ -644,9 +639,13 @@ bool cachefiles_look_up_object(struct cachefiles_object *object)
644639
645640 if (!d_is_reg (dentry )) {
646641 pr_err ("%pd is not a file\n" , dentry );
647- inode_lock_nested (d_inode (fan ), I_MUTEX_PARENT );
648- ret = cachefiles_bury_object (volume -> cache , object , fan , dentry ,
649- FSCACHE_OBJECT_IS_WEIRD );
642+ struct dentry * de = start_removing_dentry (fan , dentry );
643+ if (IS_ERR (de ))
644+ ret = PTR_ERR (de );
645+ else
646+ ret = cachefiles_bury_object (volume -> cache , object ,
647+ fan , de ,
648+ FSCACHE_OBJECT_IS_WEIRD );
650649 dput (dentry );
651650 if (ret < 0 )
652651 return false;
@@ -679,36 +678,41 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
679678
680679 _enter (",%pD" , object -> file );
681680
682- inode_lock_nested (d_inode (fan ), I_MUTEX_PARENT );
683681 ret = cachefiles_inject_read_error ();
684682 if (ret == 0 )
685- dentry = lookup_one (& nop_mnt_idmap , & QSTR (object -> d_name ), fan );
683+ dentry = start_creating (& nop_mnt_idmap , fan , & QSTR (object -> d_name ));
686684 else
687685 dentry = ERR_PTR (ret );
688686 if (IS_ERR (dentry )) {
689687 trace_cachefiles_vfs_error (object , d_inode (fan ), PTR_ERR (dentry ),
690688 cachefiles_trace_lookup_error );
691689 _debug ("lookup fail %ld" , PTR_ERR (dentry ));
692- goto out_unlock ;
690+ goto out ;
693691 }
694692
695- if (!d_is_negative (dentry )) {
693+ /*
694+ * This loop will only execute more than once if some other thread
695+ * races to create the object we are trying to create.
696+ */
697+ while (!d_is_negative (dentry )) {
696698 ret = cachefiles_unlink (volume -> cache , object , fan , dentry ,
697699 FSCACHE_OBJECT_IS_STALE );
698700 if (ret < 0 )
699- goto out_dput ;
701+ goto out_end ;
702+
703+ end_creating (dentry );
700704
701- dput (dentry );
702705 ret = cachefiles_inject_read_error ();
703706 if (ret == 0 )
704- dentry = lookup_one (& nop_mnt_idmap , & QSTR (object -> d_name ), fan );
707+ dentry = start_creating (& nop_mnt_idmap , fan ,
708+ & QSTR (object -> d_name ));
705709 else
706710 dentry = ERR_PTR (ret );
707711 if (IS_ERR (dentry )) {
708712 trace_cachefiles_vfs_error (object , d_inode (fan ), PTR_ERR (dentry ),
709713 cachefiles_trace_lookup_error );
710714 _debug ("lookup fail %ld" , PTR_ERR (dentry ));
711- goto out_unlock ;
715+ goto out ;
712716 }
713717 }
714718
@@ -729,10 +733,9 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
729733 success = true;
730734 }
731735
732- out_dput :
733- dput (dentry );
734- out_unlock :
735- inode_unlock (d_inode (fan ));
736+ out_end :
737+ end_creating (dentry );
738+ out :
736739 _leave (" = %u" , success );
737740 return success ;
738741}
@@ -748,26 +751,20 @@ static struct dentry *cachefiles_lookup_for_cull(struct cachefiles_cache *cache,
748751 struct dentry * victim ;
749752 int ret = - ENOENT ;
750753
751- inode_lock_nested ( d_inode ( dir ), I_MUTEX_PARENT );
754+ victim = start_removing ( & nop_mnt_idmap , dir , & QSTR ( filename ) );
752755
753- victim = lookup_one (& nop_mnt_idmap , & QSTR (filename ), dir );
754756 if (IS_ERR (victim ))
755757 goto lookup_error ;
756- if (d_is_negative (victim ))
757- goto lookup_put ;
758758 if (d_inode (victim )-> i_flags & S_KERNEL_FILE )
759759 goto lookup_busy ;
760760 return victim ;
761761
762762lookup_busy :
763763 ret = - EBUSY ;
764- lookup_put :
765- inode_unlock (d_inode (dir ));
766- dput (victim );
764+ end_removing (victim );
767765 return ERR_PTR (ret );
768766
769767lookup_error :
770- inode_unlock (d_inode (dir ));
771768 ret = PTR_ERR (victim );
772769 if (ret == - ENOENT )
773770 return ERR_PTR (- ESTALE ); /* Probably got retired by the netfs */
@@ -815,18 +812,17 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
815812
816813 ret = cachefiles_bury_object (cache , NULL , dir , victim ,
817814 FSCACHE_OBJECT_WAS_CULLED );
815+ dput (victim );
818816 if (ret < 0 )
819817 goto error ;
820818
821819 fscache_count_culled ();
822- dput (victim );
823820 _leave (" = 0" );
824821 return 0 ;
825822
826823error_unlock :
827- inode_unlock ( d_inode ( dir ) );
824+ end_removing ( victim );
828825error :
829- dput (victim );
830826 if (ret == - ENOENT )
831827 return - ESTALE ; /* Probably got retired by the netfs */
832828
0 commit comments