xref: /kernel/linux/linux-6.6/fs/hmdfs/file_root.c (revision 62306a36)
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
29struct 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	}
61done:
62	if (next_con)
63		peer_get(next_con);
64	mutex_unlock(&sbi->connections.node_lock);
65	return next_con;
66}
67
68int 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	}
126done:
127	kfree(remote_device_name);
128out:
129	if (err <= 0)
130		ctx->pos = -1;
131
132	return err;
133}
134
135int 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
166const struct file_operations hmdfs_root_fops = {
167	.owner = THIS_MODULE,
168	.iterate_shared = hmdfs_root_iterate,
169};
170
171const struct file_operations hmdfs_device_fops = {
172	.owner = THIS_MODULE,
173	.iterate_shared = hmdfs_device_iterate,
174};
175