1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * fs/hmdfs/hmdfs_merge_view.h 4 * 5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 6 */ 7 8#ifndef HMDFS_MERGE_VIEW_H 9#define HMDFS_MERGE_VIEW_H 10 11#include "hmdfs.h" 12 13#include "comm/connection.h" 14#include <linux/slab.h> 15#include <linux/types.h> 16#include <linux/wait.h> 17#include <linux/workqueue.h> 18 19/***************************************************************************** 20 * Dentires for merge view and their comrades. 21 * A dentry's lower dentry is named COMRADE. 22 *****************************************************************************/ 23 24struct merge_lookup_work { 25 char *name; 26 int devid; 27 unsigned int flags; 28 struct hmdfs_sb_info *sbi; 29 wait_queue_head_t *wait_queue; 30 struct work_struct work; 31}; 32 33struct hmdfs_dentry_info_merge { 34 unsigned long ctime; 35 int type; 36 int work_count; 37 struct mutex work_lock; 38 wait_queue_head_t wait_queue; 39 __u8 dentry_type; 40 struct mutex comrade_list_lock; 41 struct list_head comrade_list; 42}; 43 44struct hmdfs_dentry_comrade { 45 uint64_t dev_id; 46 struct dentry *lo_d; 47 struct list_head list; 48}; 49 50enum FILE_CMD_MERGE { 51 F_MKDIR_MERGE = 0, 52 F_CREATE_MERGE = 1, 53}; 54 55struct hmdfs_recursive_para { 56 bool is_last; 57 int opcode; 58 umode_t mode; 59 bool want_excl; 60 const char *name; 61}; 62 63struct hmdfs_rename_para { 64 struct inode *old_dir; 65 struct dentry *old_dentry; 66 struct inode *new_dir; 67 struct dentry *new_dentry; 68 unsigned int flags; 69}; 70 71static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry) 72{ 73 return dentry->d_fsdata; 74} 75 76static inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade) 77{ 78 return d_inode(comrade->lo_d)->i_mode; 79} 80 81static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade) 82{ 83 return comrade->dev_id == HMDFS_DEVID_LOCAL; 84} 85 86struct hmdfs_cache_entry *allocate_entry(const char *name, int namelen, 87 int d_type); 88 89struct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode, 90 struct dentry *child_dentry, 91 unsigned int flags); 92 93struct dentry *hmdfs_lookup_merge(struct inode *parent_inode, 94 struct dentry *child_dentry, 95 unsigned int flags); 96struct hmdfs_file_info * 97get_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id); 98 99struct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head, 100 int device_id); 101int insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry); 102struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id); 103int check_filename(const char *name, int len); 104int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi, 105 struct dentry *dentry); 106void hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para, 107 int opcode, mode_t mode, bool want_excl, 108 const char *name); 109void link_comrade(struct list_head *onstack_comrades_head, 110 struct hmdfs_dentry_comrade *comrade); 111void update_inode_attr(struct inode *inode, struct dentry *child_dentry); 112int get_num_comrades(struct dentry *dentry); 113void assign_comrades_unlocked(struct dentry *child_dentry, 114 struct list_head *onstack_comrades_head); 115struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path, 116 const char *d_name, 117 int dev_id, 118 unsigned int flags); 119bool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode); 120int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, 121 struct hmdfs_sb_info *sbi, int devid, 122 const char *name, unsigned int flags); 123char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type); 124void lock_root_inode_shared(struct inode *root, bool *locked, bool *down); 125void restore_root_inode_sem(struct inode *root, bool locked, bool down); 126int hmdfs_getattr_merge(const struct path *path, struct kstat *stat, 127 u32 request_mask, unsigned int flags); 128int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia); 129int hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry); 130int hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry); 131int hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry, 132 struct inode *new_dir, struct dentry *new_dentry, 133 unsigned int flags); 134int do_rename_merge(struct inode *old_dir, struct dentry *old_dentry, 135 struct inode *new_dir, struct dentry *new_dentry, 136 unsigned int flags); 137 138static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade) 139{ 140 dput(comrade->lo_d); 141 kfree(comrade); 142} 143 144void clear_comrades(struct dentry *dentry); 145 146static inline void link_comrade_unlocked(struct dentry *dentry, 147 struct hmdfs_dentry_comrade *comrade) 148{ 149 mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock); 150 link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade); 151 mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock); 152} 153 154void clear_comrades_locked(struct list_head *comrade_list); 155 156static inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi) 157{ 158 bool ret; 159 160 mutex_lock(&mdi->comrade_list_lock); 161 ret = list_empty(&mdi->comrade_list); 162 mutex_unlock(&mdi->comrade_list_lock); 163 164 return ret; 165} 166 167static inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi) 168{ 169 bool ret; 170 171 mutex_lock(&mdi->work_lock); 172 ret = (mdi->work_count != 0); 173 mutex_unlock(&mdi->work_lock); 174 175 return ret; 176} 177 178static inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi) 179{ 180 bool ret; 181 182 mutex_lock(&mdi->work_lock); 183 ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi); 184 mutex_unlock(&mdi->work_lock); 185 186 return ret; 187} 188 189void hmdfs_update_meta(struct inode *dir); 190 191#define for_each_comrade_locked(_dentry, _comrade) \ 192 list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list) 193 194#define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err) \ 195 { \ 196 struct hmdfs_dentry_comrade *comrade; \ 197 struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry); \ 198 _trace_func(_parent_inode, _child_dentry, err); \ 199 if (likely(dm)) { \ 200 mutex_lock(&dm->comrade_list_lock); \ 201 for_each_comrade_locked(_child_dentry, comrade) \ 202 trace_hmdfs_show_comrade(_child_dentry, \ 203 comrade->lo_d, \ 204 comrade->dev_id); \ 205 mutex_unlock(&dm->comrade_list_lock); \ 206 } \ 207 } 208 209/***************************************************************************** 210 * Helper functions abstarcting out comrade 211 *****************************************************************************/ 212 213static inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii) 214{ 215 __u8 t = hii->inode_type; 216 return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE || 217 t == HMDFS_LAYER_FIRST_MERGE_CLOUD || 218 t == HMDFS_LAYER_OTHER_MERGE_CLOUD; 219} 220 221struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id); 222struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry); 223 224/***************************************************************************** 225 * Inode operations for the merge view 226 *****************************************************************************/ 227 228extern const struct inode_operations hmdfs_file_iops_merge; 229extern const struct file_operations hmdfs_file_fops_merge; 230extern const struct inode_operations hmdfs_dir_iops_merge; 231extern const struct file_operations hmdfs_dir_fops_merge; 232extern const struct inode_operations hmdfs_file_iops_cloud_merge; 233extern const struct inode_operations hmdfs_dir_iops_cloud_merge; 234extern const struct dentry_operations hmdfs_dops_merge; 235 236/***************************************************************************** 237 * dentry cache for the merge view 238 *****************************************************************************/ 239extern struct kmem_cache *hmdfs_dentry_merge_cachep; 240 241#endif // HMDFS_MERGE_H 242