1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * fs/hmdfs/hmdfs_device_view.h
4 *
5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6 */
7
8#ifndef HMDFS_DEVICE_VIEW_H
9#define HMDFS_DEVICE_VIEW_H
10
11#include "hmdfs.h"
12
13/*****************************************************************************
14 * macro defination
15 *****************************************************************************/
16
17#define DEVICE_VIEW_ROOT "device_view"
18#define MERGE_VIEW_ROOT	 "merge_view"
19#define CLOUD_MERGE_VIEW_ROOT	 "cloud_merge_view"
20#define UPDATE_LOCAL_DST "/device_view/local/"
21#define UPDATE_CLOUD_DST "/device_view/cloud/"
22
23#define DEVICE_VIEW_LOCAL "local"
24#define DEVICE_VIEW_CLOUD "cloud"
25#define CLOUD_CID "cloud"
26#define CLOUD_DEVICE (1)
27
28/*
29 * in order to distinguish from vfs, we define our own bitmask, this should
30 * covert to vfs bitmask while calling vfs apis
31 */
32#define HMDFS_LOOKUP_REVAL 0x1
33
34enum HMDFS_FILE_TYPE {
35	HM_REG = 0,
36	HM_SYMLINK = 1,
37	HM_SHARE = 2,
38
39	HM_MAX_FILE_TYPE = 0XFF
40};
41
42struct bydev_inode_info {
43	struct inode *lower_inode;
44	uint64_t ino;
45};
46
47struct hmdfs_dentry_info {
48	struct path lower_path;
49	unsigned long time;
50	struct list_head cache_list_head;
51	spinlock_t cache_list_lock;
52	struct list_head remote_cache_list_head;
53	struct mutex remote_cache_list_lock;
54	__u8 file_type;
55	__u8 dentry_type;
56	uint64_t device_id;
57	spinlock_t lock;
58	struct mutex cache_pull_lock;
59	int async_readdir_in_progress;
60};
61
62struct hmdfs_lookup_ret {
63	uint64_t i_size;
64	uint64_t i_mtime;
65	uint32_t i_mtime_nsec;
66	uint16_t i_mode;
67	uint64_t i_ino;
68};
69
70struct hmdfs_getattr_ret {
71	/*
72	 * if stat->result_mask is 0, it means this remote getattr failed with
73	 * look up, see details in hmdfs_server_getattr.
74	 */
75	struct kstat stat;
76	uint32_t i_flags;
77	uint64_t fsid;
78};
79
80extern int hmdfs_remote_getattr(struct hmdfs_peer *conn, struct dentry *dentry,
81				unsigned int lookup_flags,
82				struct hmdfs_getattr_ret **getattr_result);
83
84/*****************************************************************************
85 * local/remote inode/file operations
86 *****************************************************************************/
87
88extern const struct dentry_operations hmdfs_dops;
89extern const struct dentry_operations hmdfs_dev_dops;
90
91/* local device operation */
92extern const struct inode_operations hmdfs_file_iops_local;
93extern const struct file_operations hmdfs_file_fops_local;
94extern const struct inode_operations hmdfs_dir_inode_ops_local;
95extern const struct file_operations hmdfs_dir_ops_local;
96extern const struct file_operations hmdfs_dir_ops_share;
97extern const struct inode_operations hmdfs_symlink_iops_local;
98extern const struct inode_operations hmdfs_dir_inode_ops_share;
99
100/* remote device operation */
101extern const struct inode_operations hmdfs_dev_file_iops_remote;
102extern const struct file_operations hmdfs_dev_file_fops_remote;
103extern const struct address_space_operations hmdfs_dev_file_aops_remote;
104extern const struct inode_operations hmdfs_dev_dir_inode_ops_remote;
105extern const struct file_operations hmdfs_dev_dir_ops_remote;
106
107/* cloud device operation */
108extern const struct inode_operations hmdfs_dev_file_iops_cloud;
109extern const struct file_operations hmdfs_dev_file_fops_cloud;
110extern const struct address_space_operations hmdfs_dev_file_aops_cloud;
111extern const struct address_space_operations hmdfs_aops_cloud;
112extern const struct inode_operations hmdfs_dev_dir_inode_ops_cloud;
113extern const struct file_operations hmdfs_dev_dir_ops_cloud;
114extern int hmdfs_dev_unlink_from_con(struct hmdfs_peer *conn,
115				     struct dentry *dentry);
116extern int hmdfs_dev_readdir_from_con(struct hmdfs_peer *con, struct file *file,
117				      struct dir_context *ctx);
118int hmdfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
119int hmdfs_rmdir(struct inode *dir, struct dentry *dentry);
120int hmdfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
121		 bool want_excl);
122int hmdfs_unlink(struct inode *dir, struct dentry *dentry);
123int hmdfs_remote_unlink(struct hmdfs_peer *conn, struct dentry *dentry);
124int hmdfs_rename(struct inode *old_dir, struct dentry *old_dentry,
125		 struct inode *new_dir, struct dentry *new_dentry,
126		 unsigned int flags);
127loff_t hmdfs_file_llseek_local(struct file *file, loff_t offset, int whence);
128
129ssize_t hmdfs_do_read_iter(struct file *file, struct iov_iter *iter,
130	loff_t *ppos);
131ssize_t hmdfs_do_write_iter(struct file *file, struct iov_iter *iter,
132	loff_t *ppos);
133
134int hmdfs_file_release_local(struct inode *inode, struct file *file);
135int hmdfs_file_mmap_local(struct file *file, struct vm_area_struct *vma);
136struct dentry *hmdfs_lookup(struct inode *parent_inode,
137			    struct dentry *child_dentry, unsigned int flags);
138struct dentry *hmdfs_lookup_local(struct inode *parent_inode,
139				  struct dentry *child_dentry,
140				  unsigned int flags);
141struct dentry *hmdfs_lookup_remote(struct inode *parent_inode,
142				   struct dentry *child_dentry,
143				   unsigned int flags);
144int hmdfs_symlink_local(struct inode *dir, struct dentry *dentry,
145			const char *symname);
146int hmdfs_fsync_local(struct file *file, loff_t start, loff_t end,
147		      int datasync);
148int hmdfs_symlink(struct inode *dir, struct dentry *dentry,
149		  const char *symname);
150int hmdfs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
151
152/*****************************************************************************
153 * common functions declaration
154 *****************************************************************************/
155
156static inline struct hmdfs_dentry_info *hmdfs_d(struct dentry *dentry)
157{
158	return dentry->d_fsdata;
159}
160
161static inline bool hm_isreg(uint8_t file_type)
162{
163	return (file_type == HM_REG);
164}
165
166static inline bool hm_islnk(uint8_t file_type)
167{
168	return (file_type == HM_SYMLINK);
169}
170
171static inline bool hm_isshare(uint8_t file_type)
172{
173	return (file_type == HM_SHARE);
174}
175
176struct inode *fill_inode_remote(struct super_block *sb, struct hmdfs_peer *con,
177				struct hmdfs_lookup_ret *lookup_result,
178				struct inode *dir);
179struct hmdfs_lookup_ret *get_remote_inode_info(struct hmdfs_peer *con,
180					       struct dentry *dentry,
181					       unsigned int flags);
182void hmdfs_set_time(struct dentry *dentry, unsigned long time);
183struct inode *fill_inode_local(struct super_block *sb,
184			       struct inode *lower_inode, const char *name);
185struct inode *fill_root_inode(struct super_block *sb,
186			      struct hmdfs_sb_info *sbi, struct inode *lower_inode);
187struct inode *fill_device_inode(struct super_block *sb,
188				struct inode *lower_inode);
189struct hmdfs_lookup_ret *hmdfs_lookup_by_con(struct hmdfs_peer *con,
190					     struct dentry *dentry,
191					     struct qstr *qstr,
192					     unsigned int flags,
193					     const char *relative_path);
194char *hmdfs_connect_path(const char *path, const char *name);
195
196char *hmdfs_get_dentry_relative_path(struct dentry *dentry);
197char *hmdfs_merge_get_dentry_relative_path(struct dentry *dentry);
198char *hmdfs_get_dentry_absolute_path(const char *rootdir,
199				     const char *relative_path);
200int hmdfs_convert_lookup_flags(unsigned int hmdfs_flags,
201			       unsigned int *vfs_flags);
202static inline void hmdfs_get_lower_path(struct dentry *dent, struct path *pname)
203{
204	spin_lock(&hmdfs_d(dent)->lock);
205	pname->dentry = hmdfs_d(dent)->lower_path.dentry;
206	pname->mnt = hmdfs_d(dent)->lower_path.mnt;
207	path_get(pname);
208	spin_unlock(&hmdfs_d(dent)->lock);
209}
210
211static inline void hmdfs_put_lower_path(struct path *pname)
212{
213	path_put(pname);
214}
215
216static inline void hmdfs_put_reset_lower_path(struct dentry *dent)
217{
218	struct path pname;
219
220	spin_lock(&hmdfs_d(dent)->lock);
221	if (hmdfs_d(dent)->lower_path.dentry) {
222		pname.dentry = hmdfs_d(dent)->lower_path.dentry;
223		pname.mnt = hmdfs_d(dent)->lower_path.mnt;
224		hmdfs_d(dent)->lower_path.dentry = NULL;
225		hmdfs_d(dent)->lower_path.mnt = NULL;
226		spin_unlock(&hmdfs_d(dent)->lock);
227		path_put(&pname);
228	} else {
229		spin_unlock(&hmdfs_d(dent)->lock);
230	}
231}
232
233static inline void hmdfs_set_lower_path(struct dentry *dent, struct path *pname)
234{
235	spin_lock(&hmdfs_d(dent)->lock);
236	hmdfs_d(dent)->lower_path.dentry = pname->dentry;
237	hmdfs_d(dent)->lower_path.mnt = pname->mnt;
238	spin_unlock(&hmdfs_d(dent)->lock);
239}
240
241/* Only reg file for HMDFS_LAYER_OTHER_* support xattr */
242static inline bool hmdfs_support_xattr(struct dentry *dentry)
243{
244	struct inode *inode = d_inode(dentry);
245	struct hmdfs_inode_info *info = hmdfs_i(inode);
246
247	if (info->inode_type != HMDFS_LAYER_OTHER_LOCAL &&
248	    info->inode_type != HMDFS_LAYER_OTHER_REMOTE &&
249	    info->inode_type != HMDFS_LAYER_OTHER_MERGE &&
250	    info->inode_type != HMDFS_LAYER_OTHER_MERGE_CLOUD)
251		return false;
252
253	if (info->inode_type == HMDFS_LAYER_OTHER_LOCAL &&
254	    hm_islnk(hmdfs_d(dentry)->file_type))
255		return false;
256
257	return true;
258}
259
260int init_hmdfs_dentry_info(struct hmdfs_sb_info *sbi, struct dentry *dentry,
261			   int dentry_type);
262
263#endif
264