• 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 CLOUD_MERGE_VIEW_CTX_POS  4
22 #define ROOT_DIR_INO_START  20000000
23 
24 // used by hmdfs_device_iterate functions
25 #define DEVICE_VIEW_INO_START 20000002
26 #define LOCAL_DEVICE_CTX_POS  2
27 #define CLOUD_DEVICE_CTX_POS  3
28 
get_next_con(struct hmdfs_sb_info * sbi,unsigned long current_dev_id)29 struct hmdfs_peer *get_next_con(struct hmdfs_sb_info *sbi,
30 				unsigned long current_dev_id)
31 {
32 	struct hmdfs_peer *con = NULL;
33 	struct hmdfs_peer *next_con = NULL;
34 	struct list_head *head, *node;
35 
36 	mutex_lock(&sbi->connections.node_lock);
37 	head = &sbi->connections.node_list;
38 	if (current_dev_id == 0) {
39 		node = head->next;
40 		if (node == head)
41 			goto done;
42 		next_con = container_of(node, struct hmdfs_peer, list);
43 		if (next_con->status == NODE_STAT_ONLINE)
44 			goto done;
45 		current_dev_id = next_con->device_id;
46 		next_con = NULL;
47 	}
48 
49 	list_for_each_entry(con, &sbi->connections.node_list, list) {
50 		if ((con->device_id & 0xFFFF) == (current_dev_id & 0xFFFF)) {
51 			node = con->list.next;
52 			if (node == head)
53 				goto done;
54 			next_con = container_of(node, struct hmdfs_peer, list);
55 			if (next_con->status == NODE_STAT_ONLINE)
56 				goto done;
57 			current_dev_id = next_con->device_id;
58 			next_con = NULL;
59 		}
60 	}
61 done:
62 	if (next_con)
63 		peer_get(next_con);
64 	mutex_unlock(&sbi->connections.node_lock);
65 	return next_con;
66 }
67 
hmdfs_device_iterate(struct file * file,struct dir_context * ctx)68 int hmdfs_device_iterate(struct file *file, struct dir_context *ctx)
69 {
70 	int err = 0;
71 	uint64_t ino_start = DEVICE_VIEW_INO_START;
72 	struct hmdfs_peer *next_con = NULL;
73 	unsigned long dev_id = 0;
74 	struct hmdfs_peer *con = NULL;
75 	char *remote_device_name = NULL;
76 
77 	if (ctx->pos != 0)
78 		goto out;
79 	dir_emit_dots(file, ctx);
80 
81 	if (ctx->pos == LOCAL_DEVICE_CTX_POS) {
82 		err = dir_emit(ctx, DEVICE_VIEW_LOCAL,
83 			       sizeof(DEVICE_VIEW_LOCAL) - 1, ino_start++,
84 			       DT_DIR);
85 		if (!err)
86 			goto out;
87 		(ctx->pos)++;
88 	}
89 
90 	if (ctx->pos == CLOUD_DEVICE_CTX_POS) {
91 		err = dir_emit(ctx, DEVICE_VIEW_CLOUD,
92 			       sizeof(DEVICE_VIEW_CLOUD) - 1, ino_start++,
93 			       DT_DIR);
94 		if (!err)
95 			goto out;
96 		(ctx->pos)++;
97 	}
98 
99 	next_con = get_next_con(file->f_inode->i_sb->s_fs_info, 0);
100 	if (!next_con)
101 		goto out;
102 
103 	dev_id = next_con->device_id;
104 	peer_put(next_con);
105 	con = hmdfs_lookup_from_devid(file->f_inode->i_sb->s_fs_info, dev_id);
106 	remote_device_name = kmalloc(HMDFS_CID_SIZE + 1, GFP_KERNEL);
107 	if (!remote_device_name) {
108 		err = -ENOMEM;
109 		goto out;
110 	}
111 	while (con) {
112 		peer_put(con);
113 		snprintf(remote_device_name, HMDFS_CID_SIZE + 1, "%s",
114 			 con->cid);
115 		if (!dir_emit(ctx, remote_device_name,
116 			      strlen(remote_device_name), ino_start++, DT_DIR))
117 			goto done;
118 
119 		(ctx->pos)++;
120 		con = get_next_con(file->f_inode->i_sb->s_fs_info, dev_id);
121 		if (!con)
122 			goto done;
123 
124 		dev_id = con->device_id;
125 	}
126 done:
127 	kfree(remote_device_name);
128 out:
129 	if (err <= 0)
130 		ctx->pos = -1;
131 
132 	return err;
133 }
134 
hmdfs_root_iterate(struct file * file,struct dir_context * ctx)135 int hmdfs_root_iterate(struct file *file, struct dir_context *ctx)
136 {
137 	uint64_t ino_start = ROOT_DIR_INO_START;
138 	struct hmdfs_sb_info *sbi = file_inode(file)->i_sb->s_fs_info;
139 
140 	if (!dir_emit_dots(file, ctx))
141 		return 0;
142 	if (ctx->pos == DEVICE_VIEW_CTX_POS) {
143 		if (!dir_emit(ctx, DEVICE_VIEW_ROOT,
144 			      sizeof(DEVICE_VIEW_ROOT) - 1, ino_start, DT_DIR))
145 			return 0;
146 		ino_start++;
147 		ctx->pos = MERGE_VIEW_CTX_POS;
148 	}
149 	if (sbi->s_merge_switch && ctx->pos == MERGE_VIEW_CTX_POS) {
150 		if (!dir_emit(ctx, MERGE_VIEW_ROOT, sizeof(MERGE_VIEW_ROOT) - 1,
151 			      ino_start, DT_DIR))
152 			return 0;
153 		ino_start++;
154 		(ctx->pos)++;
155 	}
156 	if (sbi->s_merge_switch && ctx->pos == CLOUD_MERGE_VIEW_CTX_POS) {
157 		if (!dir_emit(ctx, CLOUD_MERGE_VIEW_ROOT, sizeof(CLOUD_MERGE_VIEW_ROOT) - 1,
158 			      ino_start, DT_DIR))
159 			return 0;
160 		ino_start++;
161 		(ctx->pos)++;
162 	}
163 	return 0;
164 }
165 
166 const struct file_operations hmdfs_root_fops = {
167 	.owner = THIS_MODULE,
168 	.iterate = hmdfs_root_iterate,
169 };
170 
171 const struct file_operations hmdfs_device_fops = {
172 	.owner = THIS_MODULE,
173 	.iterate = hmdfs_device_iterate,
174 };
175