1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * fs/hmdfs/inode_cloud.c
4 *
5 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
6 */
7
8 #include <linux/fs_stack.h>
9 #include <linux/namei.h>
10 #include <linux/xattr.h>
11 #include <linux/string.h>
12
13 #include "comm/socket_adapter.h"
14 #include "hmdfs.h"
15 #include "hmdfs_client.h"
16 #include "hmdfs_dentryfile.h"
17 #include "hmdfs_dentryfile_cloud.h"
18 #include "hmdfs_share.h"
19 #include "hmdfs_trace.h"
20 #include "authority/authentication.h"
21 #include "stash.h"
22
make_ino_raw_cloud(uint8_t * cloud_id)23 uint32_t make_ino_raw_cloud(uint8_t *cloud_id)
24 {
25 struct qstr str;
26
27 str.len = CLOUD_RECORD_ID_LEN;
28 str.name = cloud_id;
29 return hmdfs_dentry_hash(&str, CLOUD_RECORD_ID_LEN);
30 }
31
lookup_cloud_dentry(struct dentry * child_dentry,const struct qstr * qstr,uint64_t dev_id)32 struct hmdfs_lookup_cloud_ret *lookup_cloud_dentry(struct dentry *child_dentry,
33 const struct qstr *qstr,
34 uint64_t dev_id)
35 {
36 struct hmdfs_lookup_cloud_ret *lookup_ret;
37 struct hmdfs_dentry_cloud *dentry = NULL;
38 struct clearcache_item *cache_item = NULL;
39 struct hmdfs_dcache_lookup_ctx_cloud ctx;
40 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
41
42 get_cloud_cache_file(child_dentry->d_parent, sbi);
43 cache_item = hmdfs_find_cache_item(dev_id, child_dentry->d_parent);
44 if (!cache_item)
45 return NULL;
46
47 lookup_ret = kmalloc(sizeof(*lookup_ret), GFP_KERNEL);
48 if (!lookup_ret)
49 goto out;
50
51 hmdfs_init_dcache_lookup_ctx_cloud(&ctx, sbi, qstr, cache_item->filp);
52 dentry = hmdfs_find_dentry_cloud(child_dentry, &ctx);
53 if (!dentry) {
54 kfree(lookup_ret);
55 lookup_ret = NULL;
56 goto out;
57 }
58
59 lookup_ret->i_mode = le16_to_cpu(dentry->i_mode);
60 lookup_ret->i_size = le64_to_cpu(dentry->i_size);
61 lookup_ret->i_mtime = le64_to_cpu(dentry->i_mtime);
62 memcpy(lookup_ret->record_id, dentry->record_id, CLOUD_RECORD_ID_LEN);
63 memcpy(lookup_ret->reserved, dentry->reserved, CLOUD_DENTRY_RESERVED_LENGTH);
64
65 hmdfs_unlock_file(ctx.filp, get_dentry_group_pos(ctx.bidx),
66 DENTRYGROUP_SIZE);
67 kfree(ctx.page);
68 out:
69 kref_put(&cache_item->ref, release_cache_item);
70 return lookup_ret;
71 }
72
73 static struct hmdfs_lookup_cloud_ret *
hmdfs_lookup_by_cloud(struct dentry * dentry,unsigned int flags)74 hmdfs_lookup_by_cloud(struct dentry *dentry, unsigned int flags)
75 {
76 struct hmdfs_lookup_cloud_ret *result = NULL;
77 char *file_name = NULL;
78 struct qstr qstr;
79 int file_name_len = dentry->d_name.len;
80
81 file_name = kzalloc(NAME_MAX + 1, GFP_KERNEL);
82 if (!file_name)
83 return NULL;
84 strncpy(file_name, dentry->d_name.name, file_name_len);
85 qstr.name = file_name;
86 qstr.len = strlen(file_name);
87
88 result = lookup_cloud_dentry(dentry, &qstr, CLOUD_DEVICE);
89
90 kfree(file_name);
91 return result;
92 }
93
94 /*
95 * hmdfs_update_inode_size - update inode size when finding aready existed
96 * inode.
97 *
98 * First of all, if the file is opened for writing, we don't update inode size
99 * here, because inode size is about to be changed after writing.
100 *
101 * If the file is not opened, simply update getattr_isize(not actual inode size,
102 * just a value showed to user). This is safe because inode size will be
103 * up-to-date after open.
104 *
105 * If the file is opened for read:
106 * a. getattr_isize == HMDFS_STALE_REMOTE_ISIZE
107 * 1) i_size == new_size, nothing need to be done.
108 * 2) i_size > new_size, we keep the i_size and set getattr_isize to new_size,
109 * stale data might be readed in this case, which is fine because file is
110 * opened before remote truncate the file.
111 * 3) i_size < new_size, we drop the last page of the file if i_size is not
112 * aligned to PAGE_SIZE, clear getattr_isize, and update i_size to
113 * new_size.
114 * b. getattr_isize != HMDFS_STALE_REMOTE_ISIZE, getattr_isize will only be set
115 * after 2).
116 * 4) getattr_isize > i_size, this situation is impossible.
117 * 5) i_size >= new_size, this case is the same as 2).
118 * 6) i_size < new_size, this case is the same as 3).
119 */
hmdfs_update_inode_size(struct inode * inode,uint64_t new_size)120 static void hmdfs_update_inode_size(struct inode *inode, uint64_t new_size)
121 {
122 struct hmdfs_inode_info *info = hmdfs_i(inode);
123 int writecount;
124 uint64_t size;
125
126 inode_lock(inode);
127 size = info->getattr_isize;
128 if (size == HMDFS_STALE_REMOTE_ISIZE)
129 size = i_size_read(inode);
130 if (size == new_size) {
131 inode_unlock(inode);
132 return;
133 }
134
135 writecount = atomic_read(&inode->i_writecount);
136 /* check if writing is in progress */
137 if (writecount > 0) {
138 info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
139 inode_unlock(inode);
140 return;
141 }
142
143 /* check if there is no one who opens the file */
144 if (kref_read(&info->ref) == 0)
145 goto update_info;
146
147 /* check if there is someone who opens the file for read */
148 if (writecount == 0) {
149 uint64_t aligned_size;
150
151 /* use inode size here instead of getattr_isize */
152 size = i_size_read(inode);
153 if (new_size <= size)
154 goto update_info;
155 /*
156 * if the old inode size is not aligned to HMDFS_PAGE_SIZE, we
157 * need to drop the last page of the inode, otherwise zero will
158 * be returned while reading the new range in the page after
159 * chaning inode size.
160 */
161 aligned_size = round_down(size, HMDFS_PAGE_SIZE);
162 if (aligned_size != size)
163 truncate_inode_pages(inode->i_mapping, aligned_size);
164 i_size_write(inode, new_size);
165 info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
166 inode_unlock(inode);
167 return;
168 }
169
170 update_info:
171 info->getattr_isize = new_size;
172 inode_unlock(inode);
173 }
174
hmdfs_update_inode(struct inode * inode,struct hmdfs_lookup_cloud_ret * lookup_result)175 static void hmdfs_update_inode(struct inode *inode,
176 struct hmdfs_lookup_cloud_ret *lookup_result)
177 {
178 struct hmdfs_time_t remote_mtime = {
179 .tv_sec = lookup_result->i_mtime,
180 .tv_nsec = 0,
181 };
182
183 /*
184 * We only update mtime if the file is not opened for writing. If we do
185 * update it before writing is about to start, user might see the mtime
186 * up-and-down if system time in server and client do not match. However
187 * mtime in client will eventually match server after timeout without
188 * writing.
189 */
190 if (!inode_is_open_for_write(inode))
191 inode->i_mtime = remote_mtime;
192
193 /*
194 * We don't care i_size of dir, and lock inode for dir
195 * might cause deadlock.
196 */
197 if (S_ISREG(inode->i_mode))
198 hmdfs_update_inode_size(inode, lookup_result->i_size);
199 }
200
hmdfs_fill_inode_permission(struct inode * inode,struct inode * dir,umode_t mode)201 static void hmdfs_fill_inode_permission(struct inode *inode, struct inode *dir,
202 umode_t mode)
203 {
204 #ifdef CONFIG_HMDFS_FS_PERMISSION
205 inode->i_uid = dir->i_uid;
206 inode->i_gid = dir->i_gid;
207 #endif
208 }
209
210 struct hmdfs_peer peer;
211
fill_inode_cloud(struct super_block * sb,struct hmdfs_lookup_cloud_ret * res,struct inode * dir)212 struct inode *fill_inode_cloud(struct super_block *sb, struct hmdfs_lookup_cloud_ret *res, struct inode *dir)
213 {
214 int ret = 0;
215 struct inode *inode = NULL;
216 struct hmdfs_inode_info *info;
217 umode_t mode = res->i_mode;
218 peer.device_id = CLOUD_DEVICE;
219
220 inode = hmdfs_iget5_locked_cloud(sb, &peer, res);
221 if (!inode)
222 return ERR_PTR(-ENOMEM);
223
224 info = hmdfs_i(inode);
225 info->inode_type = HMDFS_LAYER_OTHER_CLOUD;
226 /* the inode was found in cache */
227 if (!(inode->i_state & I_NEW)) {
228 hmdfs_fill_inode_permission(inode, dir, mode);
229 hmdfs_update_inode(inode, res);
230 return inode;
231 }
232
233 inode->i_ctime.tv_sec = 0;
234 inode->i_ctime.tv_nsec = 0;
235 inode->i_mtime.tv_sec = res->i_mtime;
236 inode->i_mtime.tv_nsec = 0;
237
238 inode->i_uid = USER_DATA_RW_UID;
239 inode->i_gid = USER_DATA_RW_GID;
240
241 if (S_ISDIR(mode))
242 inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH;
243 else if (S_ISREG(mode))
244 inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
245 else {
246 ret = -EIO;
247 goto bad_inode;
248 }
249
250 if (S_ISREG(mode)) {
251 inode->i_op = &hmdfs_dev_file_iops_cloud;
252 inode->i_fop = &hmdfs_dev_file_fops_cloud;
253 inode->i_size = res->i_size;
254 set_nlink(inode, 1);
255 } else if (S_ISDIR(mode)) {
256 inode->i_op = &hmdfs_dev_dir_inode_ops_cloud;
257 inode->i_fop = &hmdfs_dev_dir_ops_cloud;
258 set_nlink(inode, 2);
259 } else {
260 ret = -EIO;
261 goto bad_inode;
262 }
263
264 inode->i_mapping->a_ops = &hmdfs_dev_file_aops_cloud;
265
266 hmdfs_fill_inode_permission(inode, dir, mode);
267 unlock_new_inode(inode);
268 return inode;
269 bad_inode:
270 iget_failed(inode);
271 return ERR_PTR(ret);
272 }
273
hmdfs_lookup_cloud_dentry(struct inode * parent_inode,struct dentry * child_dentry,int flags)274 static struct dentry *hmdfs_lookup_cloud_dentry(struct inode *parent_inode,
275 struct dentry *child_dentry,
276 int flags)
277 {
278 struct dentry *ret = NULL;
279 struct inode *inode = NULL;
280 struct super_block *sb = parent_inode->i_sb;
281 struct hmdfs_lookup_cloud_ret *lookup_result = NULL;
282 struct hmdfs_dentry_info *gdi = hmdfs_d(child_dentry);
283
284 lookup_result = hmdfs_lookup_by_cloud(child_dentry, flags);
285 if (lookup_result != NULL) {
286 if (in_share_dir(child_dentry))
287 gdi->file_type = HM_SHARE;
288 inode = fill_inode_cloud(sb, lookup_result, parent_inode);
289
290 check_and_fixup_ownership_remote(parent_inode,
291 inode,
292 child_dentry);
293 ret = d_splice_alias(inode, child_dentry);
294 if (!IS_ERR_OR_NULL(ret))
295 child_dentry = ret;
296 } else {
297 ret = ERR_PTR(-ENOENT);
298 }
299
300 kfree(lookup_result);
301 return ret;
302 }
303
hmdfs_lookup_cloud(struct inode * parent_inode,struct dentry * child_dentry,unsigned int flags)304 struct dentry *hmdfs_lookup_cloud(struct inode *parent_inode,
305 struct dentry *child_dentry,
306 unsigned int flags)
307 {
308 int err = 0;
309 struct dentry *ret = NULL;
310 struct hmdfs_dentry_info *gdi = NULL;
311 struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
312
313 trace_hmdfs_lookup_remote(parent_inode, child_dentry, flags);
314 if (child_dentry->d_name.len > NAME_MAX) {
315 err = -ENAMETOOLONG;
316 ret = ERR_PTR(-ENAMETOOLONG);
317 goto out;
318 }
319
320 err = init_hmdfs_dentry_info(sbi, child_dentry,
321 HMDFS_LAYER_OTHER_CLOUD);
322 if (err) {
323 ret = ERR_PTR(err);
324 goto out;
325 }
326 gdi = hmdfs_d(child_dentry);
327 gdi->device_id = hmdfs_d(child_dentry->d_parent)->device_id;
328
329 ret = hmdfs_lookup_cloud_dentry(parent_inode, child_dentry, flags);
330 /*
331 * don't return error if inode do not exist, so that vfs can continue
332 * to create it.
333 */
334 if (IS_ERR_OR_NULL(ret)) {
335 err = PTR_ERR(ret);
336 if (err == -ENOENT)
337 ret = NULL;
338 } else {
339 child_dentry = ret;
340 }
341
342 out:
343 if (!err)
344 hmdfs_set_time(child_dentry, jiffies);
345 trace_hmdfs_lookup_remote_end(parent_inode, child_dentry, err);
346 return ret;
347 }
348
hmdfs_mkdir_cloud(struct inode * dir,struct dentry * dentry,umode_t mode)349 int hmdfs_mkdir_cloud(struct inode *dir, struct dentry *dentry, umode_t mode)
350 {
351 return -EPERM;
352 }
353
hmdfs_create_cloud(struct inode * dir,struct dentry * dentry,umode_t mode,bool want_excl)354 int hmdfs_create_cloud(struct inode *dir, struct dentry *dentry, umode_t mode,
355 bool want_excl)
356 {
357 return -EPERM;
358 }
359
hmdfs_rmdir_cloud(struct inode * dir,struct dentry * dentry)360 int hmdfs_rmdir_cloud(struct inode *dir, struct dentry *dentry)
361 {
362 return -EPERM;
363 }
364
hmdfs_unlink_cloud(struct inode * dir,struct dentry * dentry)365 int hmdfs_unlink_cloud(struct inode *dir, struct dentry *dentry)
366 {
367 struct hmdfs_lookup_cloud_ret *lookup_result = NULL;
368 int ret = -EPERM;
369
370 lookup_result = hmdfs_lookup_by_cloud(dentry, 0);
371 /*
372 * unlink is allowed only after the file item has been removed from
373 * the dentryfile(lookup fail).
374 */
375 if (!lookup_result)
376 ret = 0;
377
378 kfree(lookup_result);
379 return ret;
380 }
381
hmdfs_rename_cloud(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)382 int hmdfs_rename_cloud(struct inode *old_dir, struct dentry *old_dentry,
383 struct inode *new_dir, struct dentry *new_dentry,
384 unsigned int flags)
385 {
386 return -EPERM;
387 }
388
hmdfs_dir_setattr_cloud(struct dentry * dentry,struct iattr * ia)389 static int hmdfs_dir_setattr_cloud(struct dentry *dentry, struct iattr *ia)
390 {
391 // Do not support dir setattr
392 return 0;
393 }
394
395 const struct inode_operations hmdfs_dev_dir_inode_ops_cloud = {
396 .lookup = hmdfs_lookup_cloud,
397 .mkdir = hmdfs_mkdir_cloud,
398 .create = hmdfs_create_cloud,
399 .rmdir = hmdfs_rmdir_cloud,
400 .unlink = hmdfs_unlink_cloud,
401 .rename = hmdfs_rename_cloud,
402 .setattr = hmdfs_dir_setattr_cloud,
403 .permission = hmdfs_permission,
404 };
405
hmdfs_setattr_cloud(struct dentry * dentry,struct iattr * ia)406 static int hmdfs_setattr_cloud(struct dentry *dentry, struct iattr *ia)
407 {
408 struct hmdfs_inode_info *info = hmdfs_i(d_inode(dentry));
409 struct inode *inode = d_inode(dentry);
410 int err = 0;
411
412 if (hmdfs_inode_is_stashing(info))
413 return -EAGAIN;
414
415 if (ia->ia_valid & ATTR_SIZE) {
416 err = inode_newsize_ok(inode, ia->ia_size);
417 if (err)
418 return err;
419 truncate_setsize(inode, ia->ia_size);
420 info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
421 }
422 if (ia->ia_valid & ATTR_MTIME)
423 inode->i_mtime = ia->ia_mtime;
424
425 return err;
426 }
427
428
hmdfs_get_cached_attr_cloud(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)429 static int hmdfs_get_cached_attr_cloud(const struct path *path,
430 struct kstat *stat, u32 request_mask,
431 unsigned int flags)
432 {
433 struct inode *inode = d_inode(path->dentry);
434 struct hmdfs_inode_info *info = hmdfs_i(inode);
435 uint64_t size = info->getattr_isize;
436
437 stat->ino = inode->i_ino;
438 stat->mtime = inode->i_mtime;
439 stat->mode = inode->i_mode;
440 stat->uid.val = inode->i_uid.val;
441 stat->gid.val = inode->i_gid.val;
442 if (size == HMDFS_STALE_REMOTE_ISIZE)
443 size = i_size_read(inode);
444
445 stat->size = size;
446 return 0;
447 }
448
449 const struct inode_operations hmdfs_dev_file_iops_cloud = {
450 .setattr = hmdfs_setattr_cloud,
451 .permission = hmdfs_permission,
452 .getattr = hmdfs_get_cached_attr_cloud,
453 .listxattr = NULL,
454 };
455