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 = hmdfs_root_iterate, 169}; 170 171const struct file_operations hmdfs_device_fops = { 172 .owner = THIS_MODULE, 173 .iterate = hmdfs_device_iterate, 174}; 175