162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * fs/hmdfs/hmdfs_merge_view.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef HMDFS_MERGE_VIEW_H
962306a36Sopenharmony_ci#define HMDFS_MERGE_VIEW_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "hmdfs.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "comm/connection.h"
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/wait.h>
1762306a36Sopenharmony_ci#include <linux/workqueue.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*****************************************************************************
2062306a36Sopenharmony_ci * Dentires for merge view and their comrades.
2162306a36Sopenharmony_ci * A dentry's lower dentry is named COMRADE.
2262306a36Sopenharmony_ci *****************************************************************************/
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistruct merge_lookup_work {
2562306a36Sopenharmony_ci	char *name;
2662306a36Sopenharmony_ci	int devid;
2762306a36Sopenharmony_ci	unsigned int flags;
2862306a36Sopenharmony_ci	struct hmdfs_sb_info *sbi;
2962306a36Sopenharmony_ci	wait_queue_head_t *wait_queue;
3062306a36Sopenharmony_ci	struct work_struct work;
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistruct hmdfs_dentry_info_merge {
3462306a36Sopenharmony_ci	unsigned long ctime;
3562306a36Sopenharmony_ci	int type;
3662306a36Sopenharmony_ci	int work_count;
3762306a36Sopenharmony_ci	struct mutex work_lock;
3862306a36Sopenharmony_ci	wait_queue_head_t wait_queue;
3962306a36Sopenharmony_ci	__u8 dentry_type;
4062306a36Sopenharmony_ci	struct mutex comrade_list_lock;
4162306a36Sopenharmony_ci	struct list_head comrade_list;
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct hmdfs_dentry_comrade {
4562306a36Sopenharmony_ci	uint64_t dev_id;
4662306a36Sopenharmony_ci	struct dentry *lo_d;
4762306a36Sopenharmony_ci	struct list_head list;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cienum FILE_CMD_MERGE {
5162306a36Sopenharmony_ci	F_MKDIR_MERGE = 0,
5262306a36Sopenharmony_ci	F_CREATE_MERGE = 1,
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct hmdfs_recursive_para {
5662306a36Sopenharmony_ci	bool is_last;
5762306a36Sopenharmony_ci	int opcode;
5862306a36Sopenharmony_ci	umode_t mode;
5962306a36Sopenharmony_ci	bool want_excl;
6062306a36Sopenharmony_ci	const char *name;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct hmdfs_rename_para {
6462306a36Sopenharmony_ci	struct inode *old_dir;
6562306a36Sopenharmony_ci	struct dentry *old_dentry;
6662306a36Sopenharmony_ci	struct inode *new_dir;
6762306a36Sopenharmony_ci	struct dentry *new_dentry;
6862306a36Sopenharmony_ci	unsigned int flags;
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	return dentry->d_fsdata;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	return d_inode(comrade->lo_d)->i_mode;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	return comrade->dev_id == HMDFS_DEVID_LOCAL;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistruct hmdfs_cache_entry *allocate_entry(const char *name, int namelen,
8762306a36Sopenharmony_ci					 int d_type);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode,
9062306a36Sopenharmony_ci				  struct dentry *child_dentry,
9162306a36Sopenharmony_ci				  unsigned int flags);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistruct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
9462306a36Sopenharmony_ci				  struct dentry *child_dentry,
9562306a36Sopenharmony_ci				  unsigned int flags);
9662306a36Sopenharmony_cistruct hmdfs_file_info *
9762306a36Sopenharmony_ciget_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head,
10062306a36Sopenharmony_ci					    int device_id);
10162306a36Sopenharmony_ciint insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry);
10262306a36Sopenharmony_cistruct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
10362306a36Sopenharmony_ciint check_filename(const char *name, int len);
10462306a36Sopenharmony_ciint init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi,
10562306a36Sopenharmony_ci	struct dentry *dentry);
10662306a36Sopenharmony_civoid hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para,
10762306a36Sopenharmony_ci			       int opcode, mode_t mode, bool want_excl,
10862306a36Sopenharmony_ci			       const char *name);
10962306a36Sopenharmony_civoid link_comrade(struct list_head *onstack_comrades_head,
11062306a36Sopenharmony_ci		  struct hmdfs_dentry_comrade *comrade);
11162306a36Sopenharmony_civoid update_inode_attr(struct inode *inode, struct dentry *child_dentry);
11262306a36Sopenharmony_ciint get_num_comrades(struct dentry *dentry);
11362306a36Sopenharmony_civoid assign_comrades_unlocked(struct dentry *child_dentry,
11462306a36Sopenharmony_ci			      struct list_head *onstack_comrades_head);
11562306a36Sopenharmony_cistruct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path,
11662306a36Sopenharmony_ci					    const char *d_name,
11762306a36Sopenharmony_ci					    int dev_id,
11862306a36Sopenharmony_ci					    unsigned int flags);
11962306a36Sopenharmony_cibool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode);
12062306a36Sopenharmony_ciint merge_lookup_async(struct hmdfs_dentry_info_merge *mdi,
12162306a36Sopenharmony_ci		       struct hmdfs_sb_info *sbi, int devid,
12262306a36Sopenharmony_ci		       const char *name, unsigned int flags);
12362306a36Sopenharmony_cichar *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type);
12462306a36Sopenharmony_civoid lock_root_inode_shared(struct inode *root, bool *locked, bool *down);
12562306a36Sopenharmony_civoid restore_root_inode_sem(struct inode *root, bool locked, bool down);
12662306a36Sopenharmony_ciint hmdfs_getattr_merge(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat,
12762306a36Sopenharmony_ci			u32 request_mask, unsigned int flags);
12862306a36Sopenharmony_ciint hmdfs_setattr_merge(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *ia);
12962306a36Sopenharmony_ciint hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry);
13062306a36Sopenharmony_ciint hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry);
13162306a36Sopenharmony_ciint hmdfs_rename_merge(struct mnt_idmap *idmap, struct inode *old_dir, struct dentry *old_dentry,
13262306a36Sopenharmony_ci		       struct inode *new_dir, struct dentry *new_dentry,
13362306a36Sopenharmony_ci		       unsigned int flags);
13462306a36Sopenharmony_ciint do_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
13562306a36Sopenharmony_ci		    struct inode *new_dir, struct dentry *new_dentry,
13662306a36Sopenharmony_ci		    unsigned int flags);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	dput(comrade->lo_d);
14162306a36Sopenharmony_ci	kfree(comrade);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_civoid clear_comrades(struct dentry *dentry);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline void link_comrade_unlocked(struct dentry *dentry,
14762306a36Sopenharmony_ci					 struct hmdfs_dentry_comrade *comrade)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock);
15062306a36Sopenharmony_ci	link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade);
15162306a36Sopenharmony_ci	mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock);
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_civoid clear_comrades_locked(struct list_head *comrade_list);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	bool ret;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	mutex_lock(&mdi->comrade_list_lock);
16162306a36Sopenharmony_ci	ret = list_empty(&mdi->comrade_list);
16262306a36Sopenharmony_ci	mutex_unlock(&mdi->comrade_list_lock);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	return ret;
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	bool ret;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	mutex_lock(&mdi->work_lock);
17262306a36Sopenharmony_ci	ret = (mdi->work_count != 0);
17362306a36Sopenharmony_ci	mutex_unlock(&mdi->work_lock);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return ret;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	bool ret;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	mutex_lock(&mdi->work_lock);
18362306a36Sopenharmony_ci	ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi);
18462306a36Sopenharmony_ci	mutex_unlock(&mdi->work_lock);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	return ret;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_civoid hmdfs_update_meta(struct inode *dir);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci#define for_each_comrade_locked(_dentry, _comrade)                             \
19262306a36Sopenharmony_ci	list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list)
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err)      \
19562306a36Sopenharmony_ci	{                                                                      \
19662306a36Sopenharmony_ci		struct hmdfs_dentry_comrade *comrade;                          \
19762306a36Sopenharmony_ci		struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry);  \
19862306a36Sopenharmony_ci		_trace_func(_parent_inode, _child_dentry, err);                \
19962306a36Sopenharmony_ci		if (likely(dm)) {                                              \
20062306a36Sopenharmony_ci			mutex_lock(&dm->comrade_list_lock);                    \
20162306a36Sopenharmony_ci			for_each_comrade_locked(_child_dentry, comrade)        \
20262306a36Sopenharmony_ci				trace_hmdfs_show_comrade(_child_dentry,        \
20362306a36Sopenharmony_ci							 comrade->lo_d,        \
20462306a36Sopenharmony_ci							 comrade->dev_id);     \
20562306a36Sopenharmony_ci			mutex_unlock(&dm->comrade_list_lock);                  \
20662306a36Sopenharmony_ci		}                                                              \
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci/*****************************************************************************
21062306a36Sopenharmony_ci * Helper functions abstarcting out comrade
21162306a36Sopenharmony_ci *****************************************************************************/
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	__u8 t = hii->inode_type;
21662306a36Sopenharmony_ci	return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE ||
21762306a36Sopenharmony_ci	       t == HMDFS_LAYER_FIRST_MERGE_CLOUD ||
21862306a36Sopenharmony_ci	       t == HMDFS_LAYER_OTHER_MERGE_CLOUD;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistruct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
22262306a36Sopenharmony_cistruct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/*****************************************************************************
22562306a36Sopenharmony_ci * Inode operations for the merge view
22662306a36Sopenharmony_ci *****************************************************************************/
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ciextern const struct inode_operations hmdfs_file_iops_merge;
22962306a36Sopenharmony_ciextern const struct file_operations hmdfs_file_fops_merge;
23062306a36Sopenharmony_ciextern const struct inode_operations hmdfs_dir_iops_merge;
23162306a36Sopenharmony_ciextern const struct file_operations hmdfs_dir_fops_merge;
23262306a36Sopenharmony_ciextern const struct inode_operations hmdfs_file_iops_cloud_merge;
23362306a36Sopenharmony_ciextern const struct inode_operations hmdfs_dir_iops_cloud_merge;
23462306a36Sopenharmony_ciextern const struct dentry_operations hmdfs_dops_merge;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/*****************************************************************************
23762306a36Sopenharmony_ci * dentry cache for the merge view
23862306a36Sopenharmony_ci *****************************************************************************/
23962306a36Sopenharmony_ciextern struct kmem_cache *hmdfs_dentry_merge_cachep;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci#endif // HMDFS_MERGE_H
242