• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/hmdfs/file_root.c
4  *
5  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6  */
7 
8 #include <linux/fs_stack.h>
9 #include <linux/mount.h>
10 #include <linux/namei.h>
11 
12 #include "authority/authentication.h"
13 #include "comm/socket_adapter.h"
14 #include "comm/transport.h"
15 #include "hmdfs.h"
16 #include "hmdfs_dentryfile.h"
17 #include "hmdfs_device_view.h"
18 
19 #define DEVICE_VIEW_CTX_POS 2
20 #define MERGE_VIEW_CTX_POS  3
21 #define ROOT_DIR_INO_START  20000000
22 
23 // used by hmdfs_device_iterate functions
24 #define DEVICE_VIEW_INO_START 20000002
25 #define LOCAL_DEVICE_CTX_POS  2
26 
get_next_con(struct hmdfs_sb_info * sbi,unsigned long current_dev_id)27 struct hmdfs_peer *get_next_con(struct hmdfs_sb_info *sbi,
28 				unsigned long current_dev_id)
29 {
30 	struct hmdfs_peer *con = NULL;
31 	struct hmdfs_peer *next_con = NULL;
32 	struct list_head *head, *node;
33 
34 	mutex_lock(&sbi->connections.node_lock);
35 	head = &sbi->connections.node_list;
36 	if (current_dev_id == 0) {
37 		node = head->next;
38 		if (node == head)
39 			goto done;
40 		next_con = container_of(node, struct hmdfs_peer, list);
41 		if (next_con->status == NODE_STAT_ONLINE)
42 			goto done;
43 		current_dev_id = next_con->device_id;
44 		next_con = NULL;
45 	}
46 
47 	list_for_each_entry(con, &sbi->connections.node_list, list) {
48 		if ((con->device_id & 0xFFFF) == (current_dev_id & 0xFFFF)) {
49 			node = con->list.next;
50 			if (node == head)
51 				goto done;
52 			next_con = container_of(node, struct hmdfs_peer, list);
53 			if (next_con->status == NODE_STAT_ONLINE)
54 				goto done;
55 			current_dev_id = next_con->device_id;
56 			next_con = NULL;
57 		}
58 	}
59 done:
60 	if (next_con)
61 		peer_get(next_con);
62 	mutex_unlock(&sbi->connections.node_lock);
63 	return next_con;
64 }
65 
hmdfs_device_iterate(struct file * file,struct dir_context * ctx)66 int hmdfs_device_iterate(struct file *file, struct dir_context *ctx)
67 {
68 	int err = 0;
69 	uint64_t ino_start = DEVICE_VIEW_INO_START;
70 	struct hmdfs_peer *next_con = NULL;
71 	unsigned long dev_id = 0;
72 	struct hmdfs_peer *con = NULL;
73 	char *remote_device_name = NULL;
74 
75 	if (ctx->pos != 0)
76 		goto out;
77 	dir_emit_dots(file, ctx);
78 
79 	if (ctx->pos == LOCAL_DEVICE_CTX_POS) {
80 		err = dir_emit(ctx, DEVICE_VIEW_LOCAL,
81 			       sizeof(DEVICE_VIEW_LOCAL) - 1, ino_start++,
82 			       DT_DIR);
83 		if (!err)
84 			goto out;
85 		(ctx->pos)++;
86 	}
87 	next_con = get_next_con(file->f_inode->i_sb->s_fs_info, 0);
88 	if (!next_con)
89 		goto out;
90 
91 	dev_id = next_con->device_id;
92 	peer_put(next_con);
93 	con = hmdfs_lookup_from_devid(file->f_inode->i_sb->s_fs_info, dev_id);
94 	remote_device_name = kmalloc(HMDFS_CID_SIZE + 1, GFP_KERNEL);
95 	if (!remote_device_name) {
96 		err = -ENOMEM;
97 		goto out;
98 	}
99 	while (con) {
100 		peer_put(con);
101 		snprintf(remote_device_name, HMDFS_CID_SIZE + 1, "%s",
102 			 con->cid);
103 		if (!dir_emit(ctx, remote_device_name,
104 			      strlen(remote_device_name), ino_start++, DT_DIR))
105 			goto done;
106 
107 		(ctx->pos)++;
108 		con = get_next_con(file->f_inode->i_sb->s_fs_info, dev_id);
109 		if (!con)
110 			goto done;
111 
112 		dev_id = con->device_id;
113 	}
114 done:
115 	kfree(remote_device_name);
116 out:
117 	if (err <= 0)
118 		ctx->pos = -1;
119 
120 	return err;
121 }
122 
hmdfs_root_iterate(struct file * file,struct dir_context * ctx)123 int hmdfs_root_iterate(struct file *file, struct dir_context *ctx)
124 {
125 	uint64_t ino_start = ROOT_DIR_INO_START;
126 	struct hmdfs_sb_info *sbi = file_inode(file)->i_sb->s_fs_info;
127 
128 	if (!dir_emit_dots(file, ctx))
129 		return 0;
130 	if (ctx->pos == DEVICE_VIEW_CTX_POS) {
131 		if (!dir_emit(ctx, DEVICE_VIEW_ROOT,
132 			      sizeof(DEVICE_VIEW_ROOT) - 1, ino_start, DT_DIR))
133 			return 0;
134 		ino_start++;
135 		ctx->pos = MERGE_VIEW_CTX_POS;
136 	}
137 	if (sbi->s_merge_switch && ctx->pos == MERGE_VIEW_CTX_POS) {
138 		if (!dir_emit(ctx, MERGE_VIEW_ROOT, sizeof(MERGE_VIEW_ROOT) - 1,
139 			      ino_start, DT_DIR))
140 			return 0;
141 		(ctx->pos)++;
142 	}
143 	return 0;
144 }
145 
146 const struct file_operations hmdfs_root_fops = {
147 	.owner = THIS_MODULE,
148 	.iterate = hmdfs_root_iterate,
149 };
150 
151 const struct file_operations hmdfs_device_fops = {
152 	.owner = THIS_MODULE,
153 	.iterate = hmdfs_device_iterate,
154 };
155