18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/hmdfs/hmdfs_merge_view.h
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef HMDFS_MERGE_VIEW_H
98c2ecf20Sopenharmony_ci#define HMDFS_MERGE_VIEW_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "hmdfs.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "comm/connection.h"
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/types.h>
168c2ecf20Sopenharmony_ci#include <linux/wait.h>
178c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*****************************************************************************
208c2ecf20Sopenharmony_ci * Dentires for merge view and their comrades.
218c2ecf20Sopenharmony_ci * A dentry's lower dentry is named COMRADE.
228c2ecf20Sopenharmony_ci *****************************************************************************/
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistruct merge_lookup_work {
258c2ecf20Sopenharmony_ci	char *name;
268c2ecf20Sopenharmony_ci	int devid;
278c2ecf20Sopenharmony_ci	unsigned int flags;
288c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi;
298c2ecf20Sopenharmony_ci	wait_queue_head_t *wait_queue;
308c2ecf20Sopenharmony_ci	struct work_struct work;
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistruct hmdfs_dentry_info_merge {
348c2ecf20Sopenharmony_ci	unsigned long ctime;
358c2ecf20Sopenharmony_ci	int type;
368c2ecf20Sopenharmony_ci	int work_count;
378c2ecf20Sopenharmony_ci	struct mutex work_lock;
388c2ecf20Sopenharmony_ci	wait_queue_head_t wait_queue;
398c2ecf20Sopenharmony_ci	__u8 dentry_type;
408c2ecf20Sopenharmony_ci	struct mutex comrade_list_lock;
418c2ecf20Sopenharmony_ci	struct list_head comrade_list;
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistruct hmdfs_dentry_comrade {
458c2ecf20Sopenharmony_ci	uint64_t dev_id;
468c2ecf20Sopenharmony_ci	struct dentry *lo_d;
478c2ecf20Sopenharmony_ci	struct list_head list;
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cienum FILE_CMD_MERGE {
518c2ecf20Sopenharmony_ci	F_MKDIR_MERGE = 0,
528c2ecf20Sopenharmony_ci	F_CREATE_MERGE = 1,
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistruct hmdfs_recursive_para {
568c2ecf20Sopenharmony_ci	bool is_last;
578c2ecf20Sopenharmony_ci	int opcode;
588c2ecf20Sopenharmony_ci	umode_t mode;
598c2ecf20Sopenharmony_ci	bool want_excl;
608c2ecf20Sopenharmony_ci	const char *name;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct hmdfs_rename_para {
648c2ecf20Sopenharmony_ci	struct inode *old_dir;
658c2ecf20Sopenharmony_ci	struct dentry *old_dentry;
668c2ecf20Sopenharmony_ci	struct inode *new_dir;
678c2ecf20Sopenharmony_ci	struct dentry *new_dentry;
688c2ecf20Sopenharmony_ci	unsigned int flags;
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	return dentry->d_fsdata;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	return d_inode(comrade->lo_d)->i_mode;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	return comrade->dev_id == HMDFS_DEVID_LOCAL;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistruct hmdfs_cache_entry *allocate_entry(const char *name, int namelen,
878c2ecf20Sopenharmony_ci					 int d_type);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistruct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode,
908c2ecf20Sopenharmony_ci				  struct dentry *child_dentry,
918c2ecf20Sopenharmony_ci				  unsigned int flags);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
948c2ecf20Sopenharmony_ci				  struct dentry *child_dentry,
958c2ecf20Sopenharmony_ci				  unsigned int flags);
968c2ecf20Sopenharmony_cistruct hmdfs_file_info *
978c2ecf20Sopenharmony_ciget_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head,
1008c2ecf20Sopenharmony_ci					    int device_id);
1018c2ecf20Sopenharmony_ciint insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry);
1028c2ecf20Sopenharmony_cistruct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
1038c2ecf20Sopenharmony_ciint check_filename(const char *name, int len);
1048c2ecf20Sopenharmony_ciint init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi,
1058c2ecf20Sopenharmony_ci	struct dentry *dentry);
1068c2ecf20Sopenharmony_civoid hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para,
1078c2ecf20Sopenharmony_ci			       int opcode, mode_t mode, bool want_excl,
1088c2ecf20Sopenharmony_ci			       const char *name);
1098c2ecf20Sopenharmony_civoid link_comrade(struct list_head *onstack_comrades_head,
1108c2ecf20Sopenharmony_ci		  struct hmdfs_dentry_comrade *comrade);
1118c2ecf20Sopenharmony_civoid update_inode_attr(struct inode *inode, struct dentry *child_dentry);
1128c2ecf20Sopenharmony_ciint get_num_comrades(struct dentry *dentry);
1138c2ecf20Sopenharmony_civoid assign_comrades_unlocked(struct dentry *child_dentry,
1148c2ecf20Sopenharmony_ci			      struct list_head *onstack_comrades_head);
1158c2ecf20Sopenharmony_cistruct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path,
1168c2ecf20Sopenharmony_ci					    const char *d_name,
1178c2ecf20Sopenharmony_ci					    int dev_id,
1188c2ecf20Sopenharmony_ci					    unsigned int flags);
1198c2ecf20Sopenharmony_cibool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode);
1208c2ecf20Sopenharmony_ciint merge_lookup_async(struct hmdfs_dentry_info_merge *mdi,
1218c2ecf20Sopenharmony_ci		       struct hmdfs_sb_info *sbi, int devid,
1228c2ecf20Sopenharmony_ci		       const char *name, unsigned int flags);
1238c2ecf20Sopenharmony_cichar *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type);
1248c2ecf20Sopenharmony_civoid lock_root_inode_shared(struct inode *root, bool *locked, bool *down);
1258c2ecf20Sopenharmony_civoid restore_root_inode_sem(struct inode *root, bool locked, bool down);
1268c2ecf20Sopenharmony_ciint hmdfs_getattr_merge(const struct path *path, struct kstat *stat,
1278c2ecf20Sopenharmony_ci			u32 request_mask, unsigned int flags);
1288c2ecf20Sopenharmony_ciint hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia);
1298c2ecf20Sopenharmony_ciint hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry);
1308c2ecf20Sopenharmony_ciint hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry);
1318c2ecf20Sopenharmony_ciint hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
1328c2ecf20Sopenharmony_ci		       struct inode *new_dir, struct dentry *new_dentry,
1338c2ecf20Sopenharmony_ci		       unsigned int flags);
1348c2ecf20Sopenharmony_ciint do_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
1358c2ecf20Sopenharmony_ci		    struct inode *new_dir, struct dentry *new_dentry,
1368c2ecf20Sopenharmony_ci		    unsigned int flags);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	dput(comrade->lo_d);
1418c2ecf20Sopenharmony_ci	kfree(comrade);
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_civoid clear_comrades(struct dentry *dentry);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic inline void link_comrade_unlocked(struct dentry *dentry,
1478c2ecf20Sopenharmony_ci					 struct hmdfs_dentry_comrade *comrade)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock);
1508c2ecf20Sopenharmony_ci	link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade);
1518c2ecf20Sopenharmony_ci	mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock);
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_civoid clear_comrades_locked(struct list_head *comrade_list);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	bool ret;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	mutex_lock(&mdi->comrade_list_lock);
1618c2ecf20Sopenharmony_ci	ret = list_empty(&mdi->comrade_list);
1628c2ecf20Sopenharmony_ci	mutex_unlock(&mdi->comrade_list_lock);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	return ret;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	bool ret;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	mutex_lock(&mdi->work_lock);
1728c2ecf20Sopenharmony_ci	ret = (mdi->work_count != 0);
1738c2ecf20Sopenharmony_ci	mutex_unlock(&mdi->work_lock);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	return ret;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	bool ret;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	mutex_lock(&mdi->work_lock);
1838c2ecf20Sopenharmony_ci	ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi);
1848c2ecf20Sopenharmony_ci	mutex_unlock(&mdi->work_lock);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	return ret;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_civoid hmdfs_update_meta(struct inode *dir);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci#define for_each_comrade_locked(_dentry, _comrade)                             \
1928c2ecf20Sopenharmony_ci	list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list)
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci#define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err)      \
1958c2ecf20Sopenharmony_ci	{                                                                      \
1968c2ecf20Sopenharmony_ci		struct hmdfs_dentry_comrade *comrade;                          \
1978c2ecf20Sopenharmony_ci		struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry);  \
1988c2ecf20Sopenharmony_ci		_trace_func(_parent_inode, _child_dentry, err);                \
1998c2ecf20Sopenharmony_ci		if (likely(dm)) {                                              \
2008c2ecf20Sopenharmony_ci			mutex_lock(&dm->comrade_list_lock);                    \
2018c2ecf20Sopenharmony_ci			for_each_comrade_locked(_child_dentry, comrade)        \
2028c2ecf20Sopenharmony_ci				trace_hmdfs_show_comrade(_child_dentry,        \
2038c2ecf20Sopenharmony_ci							 comrade->lo_d,        \
2048c2ecf20Sopenharmony_ci							 comrade->dev_id);     \
2058c2ecf20Sopenharmony_ci			mutex_unlock(&dm->comrade_list_lock);                  \
2068c2ecf20Sopenharmony_ci		}                                                              \
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/*****************************************************************************
2108c2ecf20Sopenharmony_ci * Helper functions abstarcting out comrade
2118c2ecf20Sopenharmony_ci *****************************************************************************/
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	__u8 t = hii->inode_type;
2168c2ecf20Sopenharmony_ci	return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE ||
2178c2ecf20Sopenharmony_ci	       t == HMDFS_LAYER_FIRST_MERGE_CLOUD ||
2188c2ecf20Sopenharmony_ci	       t == HMDFS_LAYER_OTHER_MERGE_CLOUD;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistruct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
2228c2ecf20Sopenharmony_cistruct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/*****************************************************************************
2258c2ecf20Sopenharmony_ci * Inode operations for the merge view
2268c2ecf20Sopenharmony_ci *****************************************************************************/
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ciextern const struct inode_operations hmdfs_file_iops_merge;
2298c2ecf20Sopenharmony_ciextern const struct file_operations hmdfs_file_fops_merge;
2308c2ecf20Sopenharmony_ciextern const struct inode_operations hmdfs_dir_iops_merge;
2318c2ecf20Sopenharmony_ciextern const struct file_operations hmdfs_dir_fops_merge;
2328c2ecf20Sopenharmony_ciextern const struct inode_operations hmdfs_file_iops_cloud_merge;
2338c2ecf20Sopenharmony_ciextern const struct inode_operations hmdfs_dir_iops_cloud_merge;
2348c2ecf20Sopenharmony_ciextern const struct dentry_operations hmdfs_dops_merge;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci/*****************************************************************************
2378c2ecf20Sopenharmony_ci * dentry cache for the merge view
2388c2ecf20Sopenharmony_ci *****************************************************************************/
2398c2ecf20Sopenharmony_ciextern struct kmem_cache *hmdfs_dentry_merge_cachep;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci#endif // HMDFS_MERGE_H
242