* @brief Decrease reference count for a directory entry (dentry) and free if count reaches zero * * @param[in,out] dentry Pointer to the directory entry structure to be unreferenced * * @return struct dfs_dentry* The same dentry pointer if ref_count > 0, NULL if freed */
| 162 | * @return struct dfs_dentry* The same dentry pointer if ref_count > 0, NULL if freed |
| 163 | */ |
| 164 | struct dfs_dentry *dfs_dentry_unref(struct dfs_dentry *dentry) |
| 165 | { |
| 166 | rt_err_t ret = RT_EOK; |
| 167 | |
| 168 | if (dentry) |
| 169 | { |
| 170 | ret = dfs_file_lock(); |
| 171 | if (ret == RT_EOK) |
| 172 | { |
| 173 | if (dentry->flags & DENTRY_IS_ALLOCED) |
| 174 | { |
| 175 | rt_atomic_sub(&(dentry->ref_count), 1); |
| 176 | } |
| 177 | |
| 178 | if (rt_atomic_load(&(dentry->ref_count)) == 0) |
| 179 | { |
| 180 | DLOG(msg, "dentry", "dentry", DLOG_MSG, "free dentry, ref_count=0"); |
| 181 | if (dentry->flags & DENTRY_IS_ADDHASH) |
| 182 | { |
| 183 | rt_list_remove(&dentry->hashlist); |
| 184 | } |
| 185 | |
| 186 | /* release vnode */ |
| 187 | if (dentry->vnode) |
| 188 | { |
| 189 | dfs_vnode_unref(dentry->vnode); |
| 190 | } |
| 191 | |
| 192 | /* release mnt */ |
| 193 | DLOG(msg, "dentry", "mnt", DLOG_MSG, "dfs_mnt_unref(dentry->mnt)"); |
| 194 | if (dentry->mnt) |
| 195 | { |
| 196 | dfs_mnt_unref(dentry->mnt); |
| 197 | } |
| 198 | |
| 199 | dfs_file_unlock(); |
| 200 | |
| 201 | LOG_I("free a dentry: %p", dentry); |
| 202 | rt_free(dentry->pathname); |
| 203 | rt_free(dentry); |
| 204 | dentry = RT_NULL; |
| 205 | } |
| 206 | else |
| 207 | { |
| 208 | if (dentry->vnode) |
| 209 | { |
| 210 | rt_atomic_sub(&(dentry->vnode->ref_count), 1); |
| 211 | } |
| 212 | dfs_file_unlock(); |
| 213 | DLOG(note, "dentry", "dentry ref_count=%d", rt_atomic_load(&(dentry->ref_count))); |
| 214 | } |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | return dentry; |
| 219 | } |
| 220 | |
| 221 | /** |
no test coverage detected