• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/hmdfs/inode_remote.c
4  *
5  * Copyright (c) 2020-2021 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_share.h"
18 #include "hmdfs_trace.h"
19 #include "authority/authentication.h"
20 #include "stash.h"
21 
lookup_remote_dentry(struct dentry * child_dentry,const struct qstr * qstr,uint64_t dev_id)22 struct hmdfs_lookup_ret *lookup_remote_dentry(struct dentry *child_dentry,
23 					      const struct qstr *qstr,
24 					      uint64_t dev_id)
25 {
26 	struct hmdfs_lookup_ret *lookup_ret;
27 	struct hmdfs_dentry *dentry = NULL;
28 	struct clearcache_item *cache_item = NULL;
29 	struct hmdfs_dcache_lookup_ctx ctx;
30 	struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
31 
32 	cache_item = hmdfs_find_cache_item(dev_id, child_dentry->d_parent);
33 	if (!cache_item)
34 		return NULL;
35 
36 	lookup_ret = kmalloc(sizeof(*lookup_ret), GFP_KERNEL);
37 	if (!lookup_ret)
38 		goto out;
39 
40 	hmdfs_init_dcache_lookup_ctx(&ctx, sbi, qstr, cache_item->filp);
41 	dentry = hmdfs_find_dentry(child_dentry, &ctx);
42 	if (!dentry) {
43 		kfree(lookup_ret);
44 		lookup_ret = NULL;
45 		goto out;
46 	}
47 
48 	lookup_ret->i_mode = le16_to_cpu(dentry->i_mode);
49 	lookup_ret->i_size = le64_to_cpu(dentry->i_size);
50 	lookup_ret->i_mtime = le64_to_cpu(dentry->i_mtime);
51 	lookup_ret->i_mtime_nsec = le32_to_cpu(dentry->i_mtime_nsec);
52 	lookup_ret->i_ino = le64_to_cpu(dentry->i_ino);
53 
54 	hmdfs_unlock_file(ctx.filp, get_dentry_group_pos(ctx.bidx),
55 			  DENTRYGROUP_SIZE);
56 	kfree(ctx.page);
57 out:
58 	kref_put(&cache_item->ref, release_cache_item);
59 	return lookup_ret;
60 }
61 
62 /* get_remote_inode_info - fill hmdfs_lookup_ret by info from remote getattr
63  *
64  * @dentry: local dentry
65  * @hmdfs_peer: which remote devcie
66  * @flags: lookup flags
67  *
68  * return allocaed and initialized hmdfs_lookup_ret on success, and NULL on
69  * failure.
70  */
get_remote_inode_info(struct hmdfs_peer * con,struct dentry * dentry,unsigned int flags)71 struct hmdfs_lookup_ret *get_remote_inode_info(struct hmdfs_peer *con,
72 					       struct dentry *dentry,
73 					       unsigned int flags)
74 {
75 	int err = 0;
76 	struct hmdfs_lookup_ret *lookup_ret = NULL;
77 	struct hmdfs_getattr_ret *getattr_ret = NULL;
78 	unsigned int expected_flags = 0;
79 
80 	lookup_ret = kmalloc(sizeof(*lookup_ret), GFP_KERNEL);
81 	if (!lookup_ret)
82 		return NULL;
83 
84 	err = hmdfs_remote_getattr(con, dentry, flags, &getattr_ret);
85 	if (err) {
86 		hmdfs_debug("inode info get failed with err %d", err);
87 		kfree(lookup_ret);
88 		return NULL;
89 	}
90 	/* make sure we got everything we need */
91 	expected_flags = STATX_INO | STATX_SIZE | STATX_MODE | STATX_MTIME;
92 	if ((getattr_ret->stat.result_mask & expected_flags) !=
93 	    expected_flags) {
94 		hmdfs_debug("remote getattr failed with flag %x",
95 			    getattr_ret->stat.result_mask);
96 		kfree(lookup_ret);
97 		kfree(getattr_ret);
98 		return NULL;
99 	}
100 
101 	lookup_ret->i_mode = getattr_ret->stat.mode;
102 	lookup_ret->i_size = getattr_ret->stat.size;
103 	lookup_ret->i_mtime = getattr_ret->stat.mtime.tv_sec;
104 	lookup_ret->i_mtime_nsec = getattr_ret->stat.mtime.tv_nsec;
105 	lookup_ret->i_ino = getattr_ret->stat.ino;
106 	kfree(getattr_ret);
107 	return lookup_ret;
108 }
109 
hmdfs_remote_readdir_work(struct work_struct * work)110 static void hmdfs_remote_readdir_work(struct work_struct *work)
111 {
112 	struct hmdfs_readdir_work *rw =
113 		container_of(to_delayed_work(work), struct hmdfs_readdir_work,
114 			     dwork);
115 	struct dentry *dentry = rw->dentry;
116 	struct hmdfs_peer *con = rw->con;
117 	const struct cred *old_cred = hmdfs_override_creds(con->sbi->cred);
118 	bool empty = false;
119 
120 	get_remote_dentry_file(dentry, con);
121 	hmdfs_d(dentry)->async_readdir_in_progress = 0;
122 	hmdfs_revert_creds(old_cred);
123 
124 	spin_lock(&con->sbi->async_readdir_work_lock);
125 	list_del(&rw->head);
126 	empty = list_empty(&con->sbi->async_readdir_work_list);
127 	spin_unlock(&con->sbi->async_readdir_work_lock);
128 
129 	dput(dentry);
130 	peer_put(con);
131 	kfree(rw);
132 
133 	if (empty)
134 		wake_up_interruptible(&con->sbi->async_readdir_wq);
135 }
136 
get_remote_dentry_file_in_wq(struct dentry * dentry,struct hmdfs_peer * con)137 static void get_remote_dentry_file_in_wq(struct dentry *dentry,
138 					 struct hmdfs_peer *con)
139 {
140 	struct hmdfs_readdir_work *rw = NULL;
141 
142 	/* do nothing if async readdir is already in progress */
143 	if (cmpxchg_relaxed(&hmdfs_d(dentry)->async_readdir_in_progress, 0,
144 			     1))
145 		return;
146 
147 	rw = kmalloc(sizeof(*rw), GFP_KERNEL);
148 	if (!rw) {
149 		hmdfs_d(dentry)->async_readdir_in_progress = 0;
150 		return;
151 	}
152 
153 	dget(dentry);
154 	peer_get(con);
155 	rw->dentry = dentry;
156 	rw->con = con;
157 	spin_lock(&con->sbi->async_readdir_work_lock);
158 	INIT_DELAYED_WORK(&rw->dwork, hmdfs_remote_readdir_work);
159 	list_add(&rw->head, &con->sbi->async_readdir_work_list);
160 	spin_unlock(&con->sbi->async_readdir_work_lock);
161 	queue_delayed_work(con->dentry_wq, &rw->dwork, 0);
162 }
163 
get_remote_dentry_file_sync(struct dentry * dentry,struct hmdfs_peer * con)164 void get_remote_dentry_file_sync(struct dentry *dentry, struct hmdfs_peer *con)
165 {
166 	get_remote_dentry_file_in_wq(dentry, con);
167 	flush_workqueue(con->dentry_wq);
168 }
169 
hmdfs_lookup_by_con(struct hmdfs_peer * con,struct dentry * dentry,struct qstr * qstr,unsigned int flags,const char * relative_path)170 struct hmdfs_lookup_ret *hmdfs_lookup_by_con(struct hmdfs_peer *con,
171 					     struct dentry *dentry,
172 					     struct qstr *qstr,
173 					     unsigned int flags,
174 					     const char *relative_path)
175 {
176 	struct hmdfs_lookup_ret *result = NULL;
177 
178 	/*
179 		* LOOKUP_REVAL means we found stale info from dentry file, thus
180 		* we need to use remote getattr.
181 		*/
182 	if (flags & LOOKUP_REVAL) {
183 		/*
184 			* HMDFS_LOOKUP_REVAL means we need to skip dentry cache
185 			* in lookup, because dentry cache in server might have
186 			* stale data.
187 			*/
188 		result = get_remote_inode_info(con, dentry,
189 						HMDFS_LOOKUP_REVAL);
190 		get_remote_dentry_file_in_wq(dentry->d_parent, con);
191 		return result;
192 	}
193 
194 	/* If cache file is still valid */
195 	if (hmdfs_cache_revalidate(READ_ONCE(con->conn_time),
196 					con->device_id, dentry->d_parent)) {
197 		result = lookup_remote_dentry(dentry, qstr,
198 						con->device_id);
199 		/*
200 			* If lookup from cache file failed, use getattr to see
201 			* if remote have created the file.
202 			*/
203 		if (!(flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) &&
204 			!result)
205 			result = get_remote_inode_info(con, dentry, 0);
206 		/* If cache file expired, use getattr directly
207 			* except create and rename opt
208 			*/
209 	} else {
210 		result = get_remote_inode_info(con, dentry, 0);
211 		get_remote_dentry_file_in_wq(dentry->d_parent, con);
212 	}
213 
214 	return result;
215 }
216 
217 /*
218  * hmdfs_update_inode_size - update inode size when finding aready existed
219  * inode.
220  *
221  * First of all, if the file is opened for writing, we don't update inode size
222  * here, because inode size is about to be changed after writing.
223  *
224  * If the file is not opened, simply update getattr_isize(not actual inode size,
225  * just a value showed to user). This is safe because inode size will be
226  * up-to-date after open.
227  *
228  * If the file is opened for read:
229  * a. getattr_isize == HMDFS_STALE_REMOTE_ISIZE
230  *   1) i_size == new_size, nothing need to be done.
231  *   2) i_size > new_size, we keep the i_size and set getattr_isize to new_size,
232  *      stale data might be readed in this case, which is fine because file is
233  *      opened before remote truncate the file.
234  *   3) i_size < new_size, we drop the last page of the file if i_size is not
235  *      aligned to PAGE_SIZE, clear getattr_isize, and update i_size to
236  *      new_size.
237  * b. getattr_isize != HMDFS_STALE_REMOTE_ISIZE, getattr_isize will only be set
238  *    after 2).
239  *   4) getattr_isize > i_size, this situation is impossible.
240  *   5) i_size >= new_size, this case is the same as 2).
241  *   6) i_size < new_size, this case is the same as 3).
242  */
hmdfs_update_inode_size(struct inode * inode,uint64_t new_size)243 static void hmdfs_update_inode_size(struct inode *inode, uint64_t new_size)
244 {
245 	struct hmdfs_inode_info *info = hmdfs_i(inode);
246 	int writecount;
247 	uint64_t size;
248 
249 	inode_lock(inode);
250 	size = info->getattr_isize;
251 	if (size == HMDFS_STALE_REMOTE_ISIZE)
252 		size = i_size_read(inode);
253 	if (size == new_size) {
254 		inode_unlock(inode);
255 		return;
256 	}
257 
258 	writecount = atomic_read(&inode->i_writecount);
259 	/* check if writing is in progress */
260 	if (writecount > 0) {
261 		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
262 		inode_unlock(inode);
263 		return;
264 	}
265 
266 	/* check if there is no one who opens the file */
267 	if (kref_read(&info->ref) == 0)
268 		goto update_info;
269 
270 	/* check if there is someone who opens the file for read */
271 	if (writecount == 0) {
272 		uint64_t aligned_size;
273 
274 		/* use inode size here instead of getattr_isize */
275 		size = i_size_read(inode);
276 		if (new_size <= size)
277 			goto update_info;
278 		/*
279 		 * if the old inode size is not aligned to HMDFS_PAGE_SIZE, we
280 		 * need to drop the last page of the inode, otherwise zero will
281 		 * be returned while reading the new range in the page after
282 		 * chaning inode size.
283 		 */
284 		aligned_size = round_down(size, HMDFS_PAGE_SIZE);
285 		if (aligned_size != size)
286 			truncate_inode_pages(inode->i_mapping, aligned_size);
287 		i_size_write(inode, new_size);
288 		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
289 		inode_unlock(inode);
290 		return;
291 	}
292 
293 update_info:
294 	info->getattr_isize = new_size;
295 	inode_unlock(inode);
296 }
297 
hmdfs_update_inode(struct inode * inode,struct hmdfs_lookup_ret * lookup_result)298 static void hmdfs_update_inode(struct inode *inode,
299 			       struct hmdfs_lookup_ret *lookup_result)
300 {
301 	struct hmdfs_time_t remote_mtime = {
302 		.tv_sec = lookup_result->i_mtime,
303 		.tv_nsec = lookup_result->i_mtime_nsec,
304 	};
305 
306 	/*
307 	 * We only update mtime if the file is not opened for writing. If we do
308 	 * update it before writing is about to start, user might see the mtime
309 	 * up-and-down if system time in server and client do not match. However
310 	 * mtime in client will eventually match server after timeout without
311 	 * writing.
312 	 */
313 	if (!inode_is_open_for_write(inode))
314 		inode->i_mtime = remote_mtime;
315 
316 	/*
317 	 * We don't care i_size of dir, and lock inode for dir
318 	 * might cause deadlock.
319 	 */
320 	if (S_ISREG(inode->i_mode))
321 		hmdfs_update_inode_size(inode, lookup_result->i_size);
322 }
323 
hmdfs_fill_inode_remote(struct inode * inode,struct inode * dir,umode_t mode)324 static void hmdfs_fill_inode_remote(struct inode *inode, struct inode *dir,
325 				     umode_t mode)
326 {
327 #ifdef CONFIG_HMDFS_FS_PERMISSION
328 	inode->i_uid = dir->i_uid;
329 	inode->i_gid = dir->i_gid;
330 #endif
331 }
332 
fill_inode_remote(struct super_block * sb,struct hmdfs_peer * con,struct hmdfs_lookup_ret * res,struct inode * dir)333 struct inode *fill_inode_remote(struct super_block *sb, struct hmdfs_peer *con,
334 				struct hmdfs_lookup_ret *res, struct inode *dir)
335 {
336 	int ret = 0;
337 	struct inode *inode = NULL;
338 	struct hmdfs_inode_info *info;
339 	umode_t mode = res->i_mode;
340 
341 	inode = hmdfs_iget5_locked_remote(sb, con, res->i_ino);
342 	if (!inode)
343 		return ERR_PTR(-ENOMEM);
344 
345 	info = hmdfs_i(inode);
346 	info->inode_type = HMDFS_LAYER_OTHER_REMOTE;
347 
348 	/* the inode was found in cache */
349 	if (!(inode->i_state & I_NEW)) {
350 		hmdfs_fill_inode_remote(inode, dir, mode);
351 		hmdfs_update_inode(inode, res);
352 		return inode;
353 	}
354 
355 	hmdfs_remote_init_stash_status(con, inode, mode);
356 
357 	inode->i_ctime.tv_sec = 0;
358 	inode->i_ctime.tv_nsec = 0;
359 	inode->i_mtime.tv_sec = res->i_mtime;
360 	inode->i_mtime.tv_nsec = res->i_mtime_nsec;
361 
362 	inode->i_uid = KUIDT_INIT((uid_t)1000);
363 	inode->i_gid = KGIDT_INIT((gid_t)1000);
364 
365 	if (S_ISDIR(mode))
366 		inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH;
367 	else if (S_ISREG(mode))
368 		inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
369 	else if (S_ISLNK(mode))
370 		inode->i_mode = S_IFREG | S_IRWXU | S_IRWXG;
371 	else {
372 		ret = -EIO;
373 		goto bad_inode;
374 	}
375 
376 	if (S_ISREG(mode) || S_ISLNK(mode)) {
377 		inode->i_op = &hmdfs_dev_file_iops_remote;
378 		inode->i_fop = &hmdfs_dev_file_fops_remote;
379 		inode->i_size = res->i_size;
380 		set_nlink(inode, 1);
381 	} else if (S_ISDIR(mode)) {
382 		inode->i_op = &hmdfs_dev_dir_inode_ops_remote;
383 		inode->i_fop = &hmdfs_dev_dir_ops_remote;
384 		set_nlink(inode, 2);
385 	} else {
386 		ret = -EIO;
387 		goto bad_inode;
388 	}
389 
390 	inode->i_mapping->a_ops = &hmdfs_dev_file_aops_remote;
391 
392 	hmdfs_fill_inode_remote(inode, dir, mode);
393 	unlock_new_inode(inode);
394 	return inode;
395 bad_inode:
396 	iget_failed(inode);
397 	return ERR_PTR(ret);
398 }
399 
hmdfs_lookup_remote_dentry(struct inode * parent_inode,struct dentry * child_dentry,int flags)400 static struct dentry *hmdfs_lookup_remote_dentry(struct inode *parent_inode,
401 						 struct dentry *child_dentry,
402 						 int flags)
403 {
404 	struct dentry *ret = NULL;
405 	struct inode *inode = NULL;
406 	struct super_block *sb = parent_inode->i_sb;
407 	struct hmdfs_sb_info *sbi = sb->s_fs_info;
408 	struct hmdfs_lookup_ret *lookup_result = NULL;
409 	struct hmdfs_peer *con = NULL;
410 	char *file_name = NULL;
411 	int file_name_len = child_dentry->d_name.len;
412 	struct qstr qstr;
413 	struct hmdfs_dentry_info *gdi = hmdfs_d(child_dentry);
414 	uint64_t device_id = 0;
415 	char *relative_path = NULL;
416 
417 	file_name = kzalloc(NAME_MAX + 1, GFP_KERNEL);
418 	if (!file_name)
419 		return ERR_PTR(-ENOMEM);
420 	strncpy(file_name, child_dentry->d_name.name, file_name_len);
421 
422 	qstr.name = file_name;
423 	qstr.len = strlen(file_name);
424 
425 	device_id = gdi->device_id;
426 	con = hmdfs_lookup_from_devid(sbi, device_id);
427 	if (!con) {
428 		ret = ERR_PTR(-ESHUTDOWN);
429 		goto done;
430 	}
431 
432 	relative_path = hmdfs_get_dentry_relative_path(child_dentry->d_parent);
433 	if (unlikely(!relative_path)) {
434 		ret = ERR_PTR(-ENOMEM);
435 		hmdfs_err("get relative path failed %d", -ENOMEM);
436 		goto done;
437 	}
438 
439 	lookup_result = hmdfs_lookup_by_con(con, child_dentry, &qstr, flags,
440 					    relative_path);
441 	if (lookup_result != NULL) {
442 		if (S_ISLNK(lookup_result->i_mode))
443 			gdi->file_type = HM_SYMLINK;
444 		else if (in_share_dir(child_dentry))
445 			gdi->file_type = HM_SHARE;
446 		inode = fill_inode_remote(sb, con, lookup_result, parent_inode);
447 		check_and_fixup_ownership_remote(parent_inode,
448 						 inode,
449 						 child_dentry);
450 		ret = d_splice_alias(inode, child_dentry);
451 		if (!IS_ERR_OR_NULL(ret))
452 			child_dentry = ret;
453 	} else {
454 		ret = ERR_PTR(-ENOENT);
455 	}
456 
457 done:
458 	if (con)
459 		peer_put(con);
460 	kfree(relative_path);
461 	kfree(lookup_result);
462 	kfree(file_name);
463 	return ret;
464 }
465 
hmdfs_lookup_remote(struct inode * parent_inode,struct dentry * child_dentry,unsigned int flags)466 struct dentry *hmdfs_lookup_remote(struct inode *parent_inode,
467 				   struct dentry *child_dentry,
468 				   unsigned int flags)
469 {
470 	int err = 0;
471 	struct dentry *ret = NULL;
472 	struct hmdfs_dentry_info *gdi = NULL;
473 	struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
474 
475 	trace_hmdfs_lookup_remote(parent_inode, child_dentry, flags);
476 	if (child_dentry->d_name.len > NAME_MAX) {
477 		err = -ENAMETOOLONG;
478 		ret = ERR_PTR(-ENAMETOOLONG);
479 		goto out;
480 	}
481 
482 	err = init_hmdfs_dentry_info(sbi, child_dentry,
483 				     HMDFS_LAYER_OTHER_REMOTE);
484 	if (err) {
485 		ret = ERR_PTR(err);
486 		goto out;
487 	}
488 	gdi = hmdfs_d(child_dentry);
489 	gdi->device_id = hmdfs_d(child_dentry->d_parent)->device_id;
490 
491 	if (is_current_hmdfs_server_ctx())
492 		goto out;
493 
494 	ret = hmdfs_lookup_remote_dentry(parent_inode, child_dentry, flags);
495 	/*
496 	 * don't return error if inode do not exist, so that vfs can continue
497 	 * to create it.
498 	 */
499 	if (IS_ERR_OR_NULL(ret)) {
500 		err = PTR_ERR(ret);
501 		if (err == -ENOENT)
502 			ret = NULL;
503 	} else {
504 		child_dentry = ret;
505 	}
506 
507 out:
508 	if (!err)
509 		hmdfs_set_time(child_dentry, jiffies);
510 	trace_hmdfs_lookup_remote_end(parent_inode, child_dentry, err);
511 	return ret;
512 }
513 
514 /* delete dentry in cache file */
delete_in_cache_file(uint64_t dev_id,struct dentry * dentry)515 void delete_in_cache_file(uint64_t dev_id, struct dentry *dentry)
516 {
517 	struct clearcache_item *item = NULL;
518 
519 	item = hmdfs_find_cache_item(dev_id, dentry->d_parent);
520 	if (item) {
521 		hmdfs_delete_dentry(dentry, item->filp);
522 		kref_put(&item->ref, release_cache_item);
523 	} else {
524 		hmdfs_info("find cache item failed, con:%llu", dev_id);
525 	}
526 }
527 
hmdfs_mkdir_remote_dentry(struct hmdfs_peer * conn,struct dentry * dentry,umode_t mode)528 int hmdfs_mkdir_remote_dentry(struct hmdfs_peer *conn, struct dentry *dentry,
529 			      umode_t mode)
530 {
531 	int err = 0;
532 	char *dir_path = NULL;
533 	struct dentry *parent_dentry = dentry->d_parent;
534 	struct inode *parent_inode = d_inode(parent_dentry);
535 	struct super_block *sb = parent_inode->i_sb;
536 	const unsigned char *d_name = dentry->d_name.name;
537 	struct hmdfs_lookup_ret *mkdir_ret = NULL;
538 	struct inode *inode = NULL;
539 
540 	mkdir_ret = kmalloc(sizeof(*mkdir_ret), GFP_KERNEL);
541 	if (!mkdir_ret) {
542 		err = -ENOMEM;
543 		return err;
544 	}
545 	dir_path = hmdfs_get_dentry_relative_path(parent_dentry);
546 	if (!dir_path) {
547 		err = -EACCES;
548 		goto mkdir_out;
549 	}
550 	err = hmdfs_client_start_mkdir(conn, dir_path, d_name, mode, mkdir_ret);
551 	if (err) {
552 		hmdfs_err("hmdfs_client_start_mkdir failed err = %d", err);
553 		goto mkdir_out;
554 	}
555 	if (mkdir_ret) {
556 		inode = fill_inode_remote(sb, conn, mkdir_ret, parent_inode);
557 		check_and_fixup_ownership_remote(parent_inode,
558 						 inode,
559 						 dentry);
560 		if (!IS_ERR(inode))
561 			d_add(dentry, inode);
562 		else
563 			err = PTR_ERR(inode);
564 	} else {
565 		err = -ENOENT;
566 	}
567 
568 mkdir_out:
569 	kfree(dir_path);
570 	kfree(mkdir_ret);
571 	return err;
572 }
573 
hmdfs_mkdir_remote(struct inode * dir,struct dentry * dentry,umode_t mode)574 int hmdfs_mkdir_remote(struct inode *dir, struct dentry *dentry, umode_t mode)
575 {
576 	int err = 0;
577 	struct hmdfs_inode_info *info = hmdfs_i(dir);
578 	struct hmdfs_peer *con = info->conn;
579 
580 	if (!con) {
581 		hmdfs_warning("qpb_debug: con is null!");
582 		goto out;
583 	}
584 
585 	err = hmdfs_mkdir_remote_dentry(con, dentry, mode);
586 	if (!err)
587 		create_in_cache_file(con->device_id, dentry);
588 	else
589 		hmdfs_err("remote mkdir failed err = %d", err);
590 
591 out:
592 	trace_hmdfs_mkdir_remote(dir, dentry, err);
593 	return err;
594 }
595 
hmdfs_create_remote_dentry(struct hmdfs_peer * conn,struct dentry * dentry,umode_t mode,bool want_excl)596 int hmdfs_create_remote_dentry(struct hmdfs_peer *conn, struct dentry *dentry,
597 			       umode_t mode, bool want_excl)
598 {
599 	int err = 0;
600 	char *dir_path = NULL;
601 	struct dentry *parent_dentry = dentry->d_parent;
602 	struct inode *parent_inode = d_inode(parent_dentry);
603 	struct super_block *sb = parent_inode->i_sb;
604 	const unsigned char *d_name = dentry->d_name.name;
605 	struct hmdfs_lookup_ret *create_ret = NULL;
606 	struct inode *inode = NULL;
607 
608 	create_ret = kmalloc(sizeof(*create_ret), GFP_KERNEL);
609 	if (!create_ret) {
610 		err = -ENOMEM;
611 		return err;
612 	}
613 	dir_path = hmdfs_get_dentry_relative_path(parent_dentry);
614 	if (!dir_path) {
615 		err = -EACCES;
616 		goto create_out;
617 	}
618 	err = hmdfs_client_start_create(conn, dir_path, d_name, mode,
619 					want_excl, create_ret);
620 	if (err) {
621 		hmdfs_err("hmdfs_client_start_create failed err = %d", err);
622 		goto create_out;
623 	}
624 	if (create_ret) {
625 		inode = fill_inode_remote(sb, conn, create_ret, parent_inode);
626 		check_and_fixup_ownership_remote(parent_inode,
627 						 inode,
628 						 dentry);
629 		if (!IS_ERR(inode))
630 			d_add(dentry, inode);
631 		else
632 			err = PTR_ERR(inode);
633 	} else {
634 		err = -ENOENT;
635 		hmdfs_err("get remote inode info failed err = %d", err);
636 	}
637 
638 create_out:
639 	kfree(dir_path);
640 	kfree(create_ret);
641 	return err;
642 }
643 
hmdfs_create_remote(struct inode * dir,struct dentry * dentry,umode_t mode,bool want_excl)644 int hmdfs_create_remote(struct inode *dir, struct dentry *dentry, umode_t mode,
645 			bool want_excl)
646 {
647 	int err = 0;
648 	struct hmdfs_inode_info *info = hmdfs_i(dir);
649 	struct hmdfs_peer *con = info->conn;
650 
651 	if (!con) {
652 		hmdfs_warning("qpb_debug: con is null!");
653 		goto out;
654 	}
655 
656 	err = hmdfs_create_remote_dentry(con, dentry, mode, want_excl);
657 	if (!err)
658 		create_in_cache_file(con->device_id, dentry);
659 	else
660 		hmdfs_err("remote create failed err = %d", err);
661 
662 out:
663 	trace_hmdfs_create_remote(dir, dentry, err);
664 	return err;
665 }
666 
hmdfs_rmdir_remote_dentry(struct hmdfs_peer * conn,struct dentry * dentry)667 int hmdfs_rmdir_remote_dentry(struct hmdfs_peer *conn, struct dentry *dentry)
668 {
669 	int error = 0;
670 	char *dir_path = NULL;
671 	const char *dentry_name = dentry->d_name.name;
672 
673 	dir_path = hmdfs_get_dentry_relative_path(dentry->d_parent);
674 	if (!dir_path) {
675 		error = -EACCES;
676 		goto rmdir_out;
677 	}
678 
679 	error = hmdfs_client_start_rmdir(conn, dir_path, dentry_name);
680 	if (!error)
681 		delete_in_cache_file(conn->device_id, dentry);
682 
683 rmdir_out:
684 	kfree(dir_path);
685 	return error;
686 }
687 
hmdfs_rmdir_remote(struct inode * dir,struct dentry * dentry)688 int hmdfs_rmdir_remote(struct inode *dir, struct dentry *dentry)
689 {
690 	int err = 0;
691 	struct hmdfs_inode_info *info = hmdfs_i(dentry->d_inode);
692 	struct hmdfs_peer *con = info->conn;
693 
694 	if (!con)
695 		goto out;
696 
697 	if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) {
698 		err = -EACCES;
699 		goto out;
700 	}
701 
702 	err = hmdfs_rmdir_remote_dentry(con, dentry);
703 	/* drop dentry even remote failed
704 	 * it maybe cause that one remote devices disconnect
705 	 * when doing remote rmdir
706 	 */
707 	d_drop(dentry);
708 out:
709 	/* return connect device's errcode */
710 	trace_hmdfs_rmdir_remote(dir, dentry, err);
711 	return err;
712 }
713 
hmdfs_dev_unlink_from_con(struct hmdfs_peer * conn,struct dentry * dentry)714 int hmdfs_dev_unlink_from_con(struct hmdfs_peer *conn, struct dentry *dentry)
715 {
716 	int error = 0;
717 	char *dir_path = NULL;
718 	const char *dentry_name = dentry->d_name.name;
719 
720 	dir_path = hmdfs_get_dentry_relative_path(dentry->d_parent);
721 	if (!dir_path) {
722 		error = -EACCES;
723 		goto unlink_out;
724 	}
725 	error = hmdfs_client_start_unlink(conn, dir_path, dentry_name);
726 	if (!error) {
727 		delete_in_cache_file(conn->device_id, dentry);
728 		drop_nlink(d_inode(dentry));
729 		d_drop(dentry);
730 	}
731 unlink_out:
732 	kfree(dir_path);
733 	return error;
734 }
735 
hmdfs_unlink_remote(struct inode * dir,struct dentry * dentry)736 int hmdfs_unlink_remote(struct inode *dir, struct dentry *dentry)
737 {
738 	struct hmdfs_inode_info *info = hmdfs_i(dentry->d_inode);
739 	struct hmdfs_peer *conn = info->conn;
740 
741 	if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON)
742 		return -EACCES;
743 
744 	if (!conn)
745 		return 0;
746 
747 	if (conn->status != NODE_STAT_ONLINE)
748 		return 0;
749 
750 	return hmdfs_dev_unlink_from_con(conn, dentry);
751 }
752 
753 /* rename dentry in cache file */
rename_in_cache_file(uint64_t dev_id,struct dentry * old_dentry,struct dentry * new_dentry)754 static void rename_in_cache_file(uint64_t dev_id, struct dentry *old_dentry,
755 				 struct dentry *new_dentry)
756 {
757 	struct clearcache_item *old_item = NULL;
758 	struct clearcache_item *new_item = NULL;
759 
760 	old_item = hmdfs_find_cache_item(dev_id, old_dentry->d_parent);
761 	new_item = hmdfs_find_cache_item(dev_id, new_dentry->d_parent);
762 	if (old_item != NULL && new_item != NULL) {
763 		hmdfs_rename_dentry(old_dentry, new_dentry, old_item->filp,
764 				    new_item->filp);
765 	} else if (old_item != NULL) {
766 		hmdfs_err("new cache item find failed!");
767 	} else if (new_item != NULL) {
768 		hmdfs_err("old cache item find failed!");
769 	} else {
770 		hmdfs_err("both cache item find failed!");
771 	}
772 
773 	if (old_item)
774 		kref_put(&old_item->ref, release_cache_item);
775 	if (new_item)
776 		kref_put(&new_item->ref, release_cache_item);
777 }
778 
hmdfs_rename_remote(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)779 int hmdfs_rename_remote(struct inode *old_dir, struct dentry *old_dentry,
780 			struct inode *new_dir, struct dentry *new_dentry,
781 			unsigned int flags)
782 {
783 	int err = 0;
784 	int ret = 0;
785 	const char *old_dentry_d_name = old_dentry->d_name.name;
786 	char *relative_old_dir_path = 0;
787 	const char *new_dentry_d_name = new_dentry->d_name.name;
788 	char *relative_new_dir_path = 0;
789 	struct hmdfs_inode_info *info = hmdfs_i(old_dentry->d_inode);
790 	struct hmdfs_peer *con = info->conn;
791 
792 	trace_hmdfs_rename_remote(old_dir, old_dentry, new_dir, new_dentry,
793 				  flags);
794 
795 	if (flags & ~RENAME_NOREPLACE)
796 		return -EINVAL;
797 
798 	if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON ||
799 	    hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) {
800 		return -EACCES;
801 	}
802 
803 	if (hmdfs_i(old_dir)->inode_type != hmdfs_i(new_dir)->inode_type) {
804 		hmdfs_err("in different view");
805 		return -EPERM;
806 	}
807 
808 	if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id)
809 		return -EXDEV;
810 
811 	relative_old_dir_path =
812 		hmdfs_get_dentry_relative_path(old_dentry->d_parent);
813 	relative_new_dir_path =
814 		hmdfs_get_dentry_relative_path(new_dentry->d_parent);
815 	if (!relative_old_dir_path || !relative_new_dir_path) {
816 		err = -EACCES;
817 		goto rename_out;
818 	}
819 	if (S_ISREG(old_dentry->d_inode->i_mode)) {
820 		hmdfs_debug("send MSG to remote devID %llu",
821 				con->device_id);
822 		err = hmdfs_client_start_rename(
823 			con, relative_old_dir_path, old_dentry_d_name,
824 			relative_new_dir_path, new_dentry_d_name,
825 			flags);
826 		if (!err)
827 			rename_in_cache_file(con->device_id, old_dentry,
828 						new_dentry);
829 	} else if (S_ISDIR(old_dentry->d_inode->i_mode)) {
830 		if ((con->status == NODE_STAT_ONLINE)) {
831 			ret = hmdfs_client_start_rename(
832 				con, relative_old_dir_path, old_dentry_d_name,
833 				relative_new_dir_path, new_dentry_d_name,
834 				flags);
835 			if (!ret)
836 				rename_in_cache_file(con->device_id, old_dentry,
837 						     new_dentry);
838 			else
839 				err = ret;
840 		}
841 	}
842 	if (!err)
843 		d_invalidate(old_dentry);
844 rename_out:
845 	kfree(relative_old_dir_path);
846 	kfree(relative_new_dir_path);
847 	return err;
848 }
849 
hmdfs_dir_setattr_remote(struct dentry * dentry,struct iattr * ia)850 static int hmdfs_dir_setattr_remote(struct dentry *dentry, struct iattr *ia)
851 {
852 	// Do not support dir setattr
853 	return 0;
854 }
855 
856 const struct inode_operations hmdfs_dev_dir_inode_ops_remote = {
857 	.lookup = hmdfs_lookup_remote,
858 	.mkdir = hmdfs_mkdir_remote,
859 	.create = hmdfs_create_remote,
860 	.rmdir = hmdfs_rmdir_remote,
861 	.unlink = hmdfs_unlink_remote,
862 	.rename = hmdfs_rename_remote,
863 	.setattr = hmdfs_dir_setattr_remote,
864 	.permission = hmdfs_permission,
865 };
866 
hmdfs_setattr_remote(struct dentry * dentry,struct iattr * ia)867 static int hmdfs_setattr_remote(struct dentry *dentry, struct iattr *ia)
868 {
869 	struct hmdfs_inode_info *info = hmdfs_i(d_inode(dentry));
870 	struct hmdfs_peer *conn = info->conn;
871 	struct inode *inode = d_inode(dentry);
872 	char *send_buf = NULL;
873 	int err = 0;
874 
875 	if (hmdfs_inode_is_stashing(info))
876 		return -EAGAIN;
877 
878 	send_buf = hmdfs_get_dentry_relative_path(dentry);
879 	if (!send_buf) {
880 		err = -ENOMEM;
881 		goto out_free;
882 	}
883 	if (ia->ia_valid & ATTR_SIZE) {
884 		err = inode_newsize_ok(inode, ia->ia_size);
885 		if (err)
886 			goto out_free;
887 		truncate_setsize(inode, ia->ia_size);
888 		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
889 	}
890 	if (ia->ia_valid & ATTR_MTIME)
891 		inode->i_mtime = ia->ia_mtime;
892 
893 	if ((ia->ia_valid & ATTR_SIZE) || (ia->ia_valid & ATTR_MTIME)) {
894 		struct setattr_info send_setattr_info = {
895 			.size = cpu_to_le64(ia->ia_size),
896 			.valid = cpu_to_le32(ia->ia_valid),
897 			.mtime = cpu_to_le64(ia->ia_mtime.tv_sec),
898 			.mtime_nsec = cpu_to_le32(ia->ia_mtime.tv_nsec),
899 		};
900 		err = hmdfs_send_setattr(conn, send_buf, &send_setattr_info);
901 	}
902 out_free:
903 	kfree(send_buf);
904 	return err;
905 }
906 
hmdfs_remote_getattr(struct hmdfs_peer * conn,struct dentry * dentry,unsigned int lookup_flags,struct hmdfs_getattr_ret ** result)907 int hmdfs_remote_getattr(struct hmdfs_peer *conn, struct dentry *dentry,
908 			 unsigned int lookup_flags,
909 			 struct hmdfs_getattr_ret **result)
910 {
911 	char *send_buf = NULL;
912 	struct hmdfs_getattr_ret *attr = NULL;
913 	int err = 0;
914 
915 	if (dentry->d_sb != conn->sbi->sb || !result)
916 		return -EINVAL;
917 
918 	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
919 	if (!attr)
920 		return -ENOMEM;
921 
922 	send_buf = hmdfs_get_dentry_relative_path(dentry);
923 	if (!send_buf) {
924 		kfree(attr);
925 		return -ENOMEM;
926 	}
927 
928 	err = hmdfs_send_getattr(conn, send_buf, lookup_flags, attr);
929 	kfree(send_buf);
930 
931 	if (err) {
932 		kfree(attr);
933 		return err;
934 	}
935 
936 	*result = attr;
937 	return 0;
938 }
939 
hmdfs_get_cached_attr_remote(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)940 static int hmdfs_get_cached_attr_remote(const struct path *path,
941 					struct kstat *stat, u32 request_mask,
942 					unsigned int flags)
943 {
944 	struct inode *inode = d_inode(path->dentry);
945 	struct hmdfs_inode_info *info = hmdfs_i(inode);
946 	uint64_t size = info->getattr_isize;
947 
948 	stat->ino = inode->i_ino;
949 	stat->mtime = inode->i_mtime;
950 	stat->mode = inode->i_mode;
951 	stat->uid.val = inode->i_uid.val;
952 	stat->gid.val = inode->i_gid.val;
953 	if (size == HMDFS_STALE_REMOTE_ISIZE)
954 		size = i_size_read(inode);
955 
956 	stat->size = size;
957 	return 0;
958 }
959 
hmdfs_remote_listxattr(struct dentry * dentry,char * list,size_t size)960 ssize_t hmdfs_remote_listxattr(struct dentry *dentry, char *list, size_t size)
961 {
962 	struct inode *inode = d_inode(dentry);
963 	struct hmdfs_inode_info *info = hmdfs_i(inode);
964 	struct hmdfs_peer *conn = info->conn;
965 	char *send_buf = NULL;
966 	ssize_t res = 0;
967 	size_t r_size = size;
968 
969 	if (!hmdfs_support_xattr(dentry))
970 		return -EOPNOTSUPP;
971 
972 	if (size > HMDFS_LISTXATTR_SIZE_MAX)
973 		r_size = HMDFS_LISTXATTR_SIZE_MAX;
974 
975 	send_buf = hmdfs_get_dentry_relative_path(dentry);
976 	if (!send_buf)
977 		return -ENOMEM;
978 
979 	res = hmdfs_send_listxattr(conn, send_buf, list, r_size);
980 	kfree(send_buf);
981 
982 	if (res == -ERANGE && r_size != size) {
983 		hmdfs_info("no support listxattr size over than %d",
984 			   HMDFS_LISTXATTR_SIZE_MAX);
985 		res = -E2BIG;
986 	}
987 
988 	return res;
989 }
990 
991 const struct inode_operations hmdfs_dev_file_iops_remote = {
992 	.setattr = hmdfs_setattr_remote,
993 	.permission = hmdfs_permission,
994 	.getattr = hmdfs_get_cached_attr_remote,
995 	.listxattr = hmdfs_remote_listxattr,
996 };
997