Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 220 additions & 8 deletions components/dfs/dfs_v2/src/dfs_mnt.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -38,6 +38,17 @@ RT_OBJECT_HOOKLIST_DEFINE(dfs_mnt_umnt);
*
*/

/**
* @brief Create a new dfs_mnt structure instance.
*
* This function allocates memory to create a new dfs_mnt structure instance and initializes it.
* If the memory allocation is successful, it copies the input path string into the instance and initializes related lists and flags.
*
* @param[in] path The path string to be mounted. This path information will be copied to the newly created dfs_mnt instance.
*
* @return If the memory allocation is successful, returns a pointer to the newly created dfs_mnt structure;
* if the memory allocation fails, returns RT_NULL.
*/
struct dfs_mnt *dfs_mnt_create(const char *path)
{
struct dfs_mnt *mnt = rt_calloc(1, sizeof(struct dfs_mnt));
Expand All @@ -59,6 +70,18 @@ struct dfs_mnt *dfs_mnt_create(const char *path)
return mnt;
}

/**
* @brief Insert a child mount point into the mount tree.
*
* This function inserts a child mount point into the specified parent mount point's child list.
* If the parent mount point is not provided, it will try to find the appropriate mount point based on the child's path.
* If the child mount point is the root, it will update the global root mount point accordingly.
*
* @param[in,out] mnt Pointer to the parent dfs_mnt structure. If NULL, it will be updated to the appropriate mount point.
* @param[in] child Pointer to the child dfs_mnt structure to be inserted.
*
* @return Always returns 0 to indicate success.
*/
int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child)
{
if (child)
Expand Down Expand Up @@ -112,7 +135,18 @@ int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child)
return 0;
}

/* remove mnt from mnt_tree */
/**
* @brief Remove a mount point from the mount tree.
*
* This function attempts to remove a specified mount point from the mount tree.
* It can only remove a mount point if it has no child mount points. If the mount point
* has children, it logs a warning message instead of performing the removal.
*
* @param[in] mnt Pointer to the dfs_mnt structure representing the mount point to be removed.
*
* @return Returns RT_EOK if the mount point is successfully removed.
* Returns -RT_ERROR if the mount point has child mount points and cannot be removed.
*/
int dfs_mnt_remove(struct dfs_mnt* mnt)
{
int ret = -RT_ERROR;
Expand All @@ -136,6 +170,19 @@ int dfs_mnt_remove(struct dfs_mnt* mnt)
return ret;
}

/**
* @brief Recursively search for a mount point associated with a specific device ID in the mount tree.
*
* This function traverses the mount tree starting from the given mount point `mnt` to find
* a mount point that is associated with the specified device ID `dev_id`. It uses a depth-first
* search algorithm to iterate through the child mount points.
*
* @param[in] mnt Pointer to the root dfs_mnt structure from which the search will start.
* @param[in] dev_id Pointer to the device ID to search for.
*
* @return If a mount point associated with the given device ID is found, returns a pointer to the corresponding dfs_mnt structure.
* Otherwise, returns RT_NULL.
*/
static struct dfs_mnt *_dfs_mnt_dev_lookup(struct dfs_mnt *mnt, rt_device_t dev_id)
{
struct dfs_mnt *ret = RT_NULL, *iter = RT_NULL;
Expand All @@ -160,6 +207,19 @@ static struct dfs_mnt *_dfs_mnt_dev_lookup(struct dfs_mnt *mnt, rt_device_t dev_
return ret;
}

/**
* @brief Search for a mount point associated with a specific device ID in the mount tree.
*
* This function initiates a search for a mount point that is associated with the specified
* device ID `dev_id` starting from the root mount point. It first checks the root mount point
* directly, and if not found, it recursively searches the entire mount tree using the
* internal helper function `_dfs_mnt_dev_lookup`.
*
* @param[in] dev_id Pointer to the device ID to search for.
*
* @return If a mount point associated with the given device ID is found, returns a pointer to the corresponding dfs_mnt structure.
* Otherwise, returns RT_NULL.
*/
struct dfs_mnt *dfs_mnt_dev_lookup(rt_device_t dev_id)
{
struct dfs_mnt *mnt = _root_mnt;
Expand All @@ -184,12 +244,16 @@ struct dfs_mnt *dfs_mnt_dev_lookup(rt_device_t dev_id)
}

/**
* this function will return the file system mounted on specified path.
* @brief Look up the mount point associated with a given full path.
*
* This function searches the mount tree starting from the root mount point to find
* the most specific mount point that matches the given full path. It traverses down
* the mount tree to identify the deepest mount point that is a prefix of the given path.
*
* @param path the specified path string.
* @param[in] fullpath The full path string for which to find the associated mount point.
*
* @return the found file system or NULL if no file system mounted on
* specified path
* @return If a matching mount point is found, returns a pointer to the corresponding dfs_mnt structure.
* Otherwise, returns RT_NULL.
*/
struct dfs_mnt *dfs_mnt_lookup(const char *fullpath)
{
Expand Down Expand Up @@ -236,6 +300,18 @@ struct dfs_mnt *dfs_mnt_lookup(const char *fullpath)
return mnt;
}

/**
* @brief Increase the reference count of a dfs_mnt structure instance.
*
* This function increments the reference count of the specified dfs_mnt structure.
* The reference count is used to track how many parts of the system are currently
* using this mount point.
*
* @param[in,out] mnt Pointer to the dfs_mnt structure whose reference count is to be increased.
* If the pointer is valid, the reference count within the structure will be modified.
* @return Returns the same pointer to the dfs_mnt structure that was passed in.
* If the input pointer is NULL, it simply returns NULL.
*/
struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt)
{
if (mnt)
Expand All @@ -247,6 +323,18 @@ struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt)
return mnt;
}

/**
* @brief Decrease the reference count of a dfs_mnt structure instance and free it if necessary.
*
* This function decrements the reference count of the specified dfs_mnt structure.
* If the reference count reaches zero after the decrement, it will perform the unmount operation,
* trigger the unmount hook, free the allocated path memory, and finally free the dfs_mnt structure itself.
*
* @param[in,out] mnt Pointer to the dfs_mnt structure whose reference count is to be decreased.
* If the reference count reaches zero, the structure will be freed.
*
* @return returns RT_EOK to indicate success.
*/
int dfs_mnt_unref(struct dfs_mnt *mnt)
{
rt_err_t ret = RT_EOK;
Expand Down Expand Up @@ -286,6 +374,19 @@ int dfs_mnt_unref(struct dfs_mnt *mnt)
return ret;
}

/**
* @brief Set specific flags for a dfs_mnt structure instance.
*
* This function sets specific flags for the given dfs_mnt structure.
* If the MS_RDONLY flag is included in the input flags, it sets the MNT_RDONLY flag
* for the mount point and cleans the page cache if the page cache feature is enabled.
*
* @param[in,out] mnt Pointer to the dfs_mnt structure for which flags are to be set.
* The structure's `flags` member will be modified if necessary.
* @param[in] flags The flags to be set for the mount point. This includes the MS_RDONLY flag.
*
* @return returns 0 to indicate success.
*/
int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags)
{
int error = 0;
Expand All @@ -301,6 +402,19 @@ int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags)
return error;
}

/**
* @brief Destroy a dfs_mnt structure instance and unmount it if necessary.
*
* This function attempts to destroy the specified dfs_mnt structure instance.
* If the mount point is currently mounted, it marks the mount point as unmounted,
* sets the unmount flag, and removes it from the mount list if it was added.
* Finally, it decreases the reference count of the mount point and frees the
* structure if the reference count reaches zero.
*
* @param[in,out] mnt Pointer to the dfs_mnt structure to be destroyed.
*
* @return Returns RT_EOK to indicate success.
*/
int dfs_mnt_destroy(struct dfs_mnt* mnt)
{
rt_err_t ret = RT_EOK;
Expand All @@ -324,6 +438,23 @@ int dfs_mnt_destroy(struct dfs_mnt* mnt)
return ret;
}

/**
* @brief Recursively traverse the mount point tree and apply a callback function.
*
* This function performs a depth-first traversal of the mount point tree starting from the given mount point.
* It applies the specified callback function to each mount point in the tree. If the callback function returns
* a non-NULL pointer, the traversal stops and the result is returned immediately.
*
* @param[in] mnt Pointer to the root dfs_mnt structure from which the traversal will start.
* If NULL, the function will return RT_NULL without performing any traversal.
* @param[in] func Pointer to the callback function to be applied to each mount point.
* The callback function takes a pointer to a dfs_mnt structure and a generic parameter,
* and returns a pointer to a dfs_mnt structure or RT_NULL.
* @param[in] parameter Generic pointer to a parameter that will be passed to the callback function.
*
* @return If the callback function returns a non-NULL pointer during the traversal, returns that pointer.
* Otherwise, returns RT_NULL.
*/
static struct dfs_mnt* _dfs_mnt_foreach(struct dfs_mnt *mnt, struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter)
{
struct dfs_mnt *iter, *ret = NULL;
Expand Down Expand Up @@ -355,6 +486,19 @@ static struct dfs_mnt* _dfs_mnt_foreach(struct dfs_mnt *mnt, struct dfs_mnt* (*f
return ret;
}

/**
* @brief Compare a mount point's device ID with a given device object.
*
* This function checks if the device ID associated with a specified mount point
* matches the given device object. If a match is found, it returns a pointer to
* the corresponding dfs_mnt structure; otherwise, it returns RT_NULL.
*
* @param[in] mnt Pointer to the dfs_mnt structure representing the mount point to be checked.
* @param[in] device Pointer to the device object to compare against the mount point's device ID.
*
* @return If the device ID of the mount point matches the given device object, returns a pointer to the dfs_mnt structure.
* Otherwise, returns RT_NULL.
*/
static struct dfs_mnt* _mnt_cmp_devid(struct dfs_mnt *mnt, void *device)
{
struct dfs_mnt *ret = RT_NULL;
Expand All @@ -374,7 +518,7 @@ static struct dfs_mnt* _mnt_cmp_devid(struct dfs_mnt *mnt, void *device)
/**
* this function will return the mounted path for specified device.
*
* @param device the device object which is mounted.
* @param[in] device the device object which is mounted.
*
* @return the mounted path or NULL if none device mounted.
*/
Expand All @@ -396,6 +540,19 @@ const char *dfs_mnt_get_mounted_path(struct rt_device *device)
return path;
}

/**
* @brief Print information about a mount point to the console.
*
* This function is designed to be used as a callback in the mount point tree traversal.
* It prints the file system name, device name (or `(NULL)` if no device is associated),
* mount path, and reference count of the specified mount point to the console using `rt_kprintf`.
*
* @param[in] mnt Pointer to the dfs_mnt structure representing the mount point to be printed.
* If NULL, the function does nothing.
* @param[in] parameter A generic pointer to a parameter. This parameter is not used in this function.
*
* @return Always returns RT_NULL as it is a callback function mainly used for side - effects (printing).
*/
static struct dfs_mnt* _mnt_dump(struct dfs_mnt *mnt, void *parameter)
{
if (mnt)
Expand All @@ -415,6 +572,22 @@ static struct dfs_mnt* _mnt_dump(struct dfs_mnt *mnt, void *parameter)
return RT_NULL;
}

/**
* @brief Compare a mount point's full path with a given path.
*
* This function is designed to be used as a callback in the mount point tree traversal.
* It compares the full path of the specified mount point with the given path.
* If the mount point's full path starts with the given path, it returns a pointer to the dfs_mnt structure;
* otherwise, it returns RT_NULL.
*
* @param[in] mnt Pointer to the dfs_mnt structure representing the mount point to be checked.
* If NULL, the function will not perform the comparison and return RT_NULL.
* @param[in] parameter A generic pointer to a parameter, which should be cast to a `const char*`
* representing the path to compare against the mount point's full path.
*
* @return If the mount point's full path starts with the given path, returns a pointer to the dfs_mnt structure.
* Otherwise, returns RT_NULL.
*/
static struct dfs_mnt* _mnt_cmp_path(struct dfs_mnt* mnt, void *parameter)
{
const char* fullpath = (const char*)parameter;
Expand All @@ -428,6 +601,22 @@ static struct dfs_mnt* _mnt_cmp_path(struct dfs_mnt* mnt, void *parameter)
return ret;
}

/**
* @brief Check if a mount point has a child mount point matching the given path.
*
* This function checks whether the specified mount point has a child mount point
* whose full path starts with the given path. It uses a depth-first traversal of
* the mount point tree starting from the provided mount point and applies the
* `_mnt_cmp_path` callback function to each mount point.
*
* @param[in] mnt Pointer to the root dfs_mnt structure from which the search will start.
* If NULL, the function will return RT_FALSE without performing any search.
* @param[in] fullpath The full path string to compare against the child mount points' paths.
* If NULL, the function will return RT_FALSE without performing any search.
*
* @return Returns RT_TRUE if a child mount point with a matching path is found.
* Returns RT_FALSE if no matching child mount point is found, or if either input parameter is NULL.
*/
rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath)
{
int ret = RT_FALSE;
Expand All @@ -449,6 +638,19 @@ rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath)
return ret;
}

/**
* @brief List all mount points starting from a specified mount point.
*
* This function lists information about all mount points in the mount point tree,
* starting from the specified mount point. If the input mount point is NULL,
* it starts from the root mount point. It uses the `_dfs_mnt_foreach` function
* with the `_mnt_dump` callback to print mount point information.
*
* @param[in] mnt Pointer to the dfs_mnt structure from which to start listing mount points.
* If NULL, the function will start from the root mount point.
*
* @return Always returns 0 to indicate success.
*/
int dfs_mnt_list(struct dfs_mnt *mnt)
{
if (!mnt) mnt = _root_mnt;
Expand All @@ -462,6 +664,16 @@ int dfs_mnt_list(struct dfs_mnt *mnt)
return 0;
}

/**
* @brief Traverse all mount points in the mount tree and apply a callback function.
*
* @param[in] func Pointer to the callback function to be applied to each mount point.
* The callback function takes a pointer to a `dfs_mnt` structure and a generic parameter,
* and returns a pointer to a `dfs_mnt` structure or `RT_NULL`.
* @param[in] parameter Generic pointer to a parameter that will be passed to the callback function.
*
* @return Always returns 0.
*/
int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter)
{
/* lock file system */
Expand All @@ -471,4 +683,4 @@ int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter
dfs_unlock();

return 0;
}
}