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