@@ -650,6 +650,99 @@ void fs_split_path(char *path, char **filename, size_t len)
650650 }
651651}
652652
653+ int fs_path_clean (const char * path , struct ltfs_index * idx )
654+ {
655+ int ret = 0 ;
656+ struct dentry * d = NULL , * parent = NULL ;
657+ char * tmp_path , * start , * end ;
658+
659+ CHECK_ARG_NULL (path , - LTFS_NULL_ARG );
660+ CHECK_ARG_NULL (idx , - LTFS_NULL_ARG );
661+
662+ tmp_path = strdup (path );
663+ if (! tmp_path ) {
664+ ltfsmsg (LTFS_ERR , 10001E , "fs_path_clean: tmp_path" );
665+ return - LTFS_NO_MEMORY ;
666+ }
667+
668+ /* Get a reference count on the root dentry. Either it will be returned immediately, or it
669+ * will be disposed later after the first path lookup. */
670+ acquirewrite_mrsw (& idx -> root -> meta_lock );
671+ ++ idx -> root -> numhandles ;
672+ releasewrite_mrsw (& idx -> root -> meta_lock );
673+
674+ if (idx -> root -> dirty )
675+ idx -> root -> dirty = false;
676+
677+ /* Did the caller ask for the root dentry? */
678+ if (* path == '\0' || ! strcmp (path , "/" )) {
679+ goto out ;
680+ }
681+
682+ start = tmp_path + 1 ;
683+ end = tmp_path ;
684+ d = idx -> root ;
685+
686+ while (end ) {
687+ end = strstr (start , "/" );
688+ if (end )
689+ * end = '\0' ;
690+
691+ acquireread_mrsw (& d -> contents_lock );
692+
693+ if (parent )
694+ releaseread_mrsw (& parent -> contents_lock );
695+ parent = d ;
696+ d = NULL ;
697+
698+ ret = fs_directory_lookup (parent , start , & d );
699+ if (ret < 0 || ! d ) {
700+ releaseread_mrsw (& parent -> contents_lock );
701+ fs_release_dentry (parent );
702+
703+ if (ret == 0 )
704+ ret = - LTFS_NO_DENTRY ;
705+ goto out ;
706+ }
707+
708+ /* Release the parent if we aren't keeping any locks on it.
709+ * Since we know 'parent' has a child (d), it's guaranteed that parent is still linked
710+ * into the file system tree. Therefore, fs_release_dentry is just a fancy way of
711+ * decrementing the handle count... so do that. */
712+ acquirewrite_mrsw (& parent -> meta_lock );
713+ -- parent -> numhandles ;
714+ releasewrite_mrsw (& parent -> meta_lock );
715+
716+ if (d -> dirty )
717+ d -> dirty = false;
718+
719+ if (end )
720+ start = end + 1 ;
721+ }
722+
723+ releaseread_mrsw (& parent -> contents_lock );
724+
725+ out :
726+ free (tmp_path );
727+
728+ return ret ;
729+ }
730+
731+ int fs_dir_clean (struct dentry * d )
732+ {
733+ struct name_list * list_ptr = NULL , * list_tmp = NULL ;
734+ CHECK_ARG_NULL (d , - LTFS_NULL_ARG );
735+
736+ if (d -> isdir ) {
737+ HASH_ITER (hh , d -> child_list , list_ptr , list_tmp ) {
738+ fs_dir_clean (list_ptr -> d );
739+ }
740+ } else
741+ d -> dirty = false;
742+
743+ return 0 ;
744+ }
745+
653746/**
654747 * Dispose a dentry and all resources used by it, including the struct dentry itself.
655748 * @param dentry dentry to dispose.
0 commit comments