162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/hmdfs/file_root.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/fs_stack.h> 962306a36Sopenharmony_ci#include <linux/mount.h> 1062306a36Sopenharmony_ci#include <linux/namei.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "authority/authentication.h" 1362306a36Sopenharmony_ci#include "comm/socket_adapter.h" 1462306a36Sopenharmony_ci#include "comm/transport.h" 1562306a36Sopenharmony_ci#include "hmdfs.h" 1662306a36Sopenharmony_ci#include "hmdfs_dentryfile.h" 1762306a36Sopenharmony_ci#include "hmdfs_device_view.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define DEVICE_VIEW_CTX_POS 2 2062306a36Sopenharmony_ci#define MERGE_VIEW_CTX_POS 3 2162306a36Sopenharmony_ci#define CLOUD_MERGE_VIEW_CTX_POS 4 2262306a36Sopenharmony_ci#define ROOT_DIR_INO_START 20000000 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci// used by hmdfs_device_iterate functions 2562306a36Sopenharmony_ci#define DEVICE_VIEW_INO_START 20000002 2662306a36Sopenharmony_ci#define LOCAL_DEVICE_CTX_POS 2 2762306a36Sopenharmony_ci#define CLOUD_DEVICE_CTX_POS 3 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct hmdfs_peer *get_next_con(struct hmdfs_sb_info *sbi, 3062306a36Sopenharmony_ci unsigned long current_dev_id) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct hmdfs_peer *con = NULL; 3362306a36Sopenharmony_ci struct hmdfs_peer *next_con = NULL; 3462306a36Sopenharmony_ci struct list_head *head, *node; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 3762306a36Sopenharmony_ci head = &sbi->connections.node_list; 3862306a36Sopenharmony_ci if (current_dev_id == 0) { 3962306a36Sopenharmony_ci node = head->next; 4062306a36Sopenharmony_ci if (node == head) 4162306a36Sopenharmony_ci goto done; 4262306a36Sopenharmony_ci next_con = container_of(node, struct hmdfs_peer, list); 4362306a36Sopenharmony_ci if (next_con->status == NODE_STAT_ONLINE) 4462306a36Sopenharmony_ci goto done; 4562306a36Sopenharmony_ci current_dev_id = next_con->device_id; 4662306a36Sopenharmony_ci next_con = NULL; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci list_for_each_entry(con, &sbi->connections.node_list, list) { 5062306a36Sopenharmony_ci if ((con->device_id & 0xFFFF) == (current_dev_id & 0xFFFF)) { 5162306a36Sopenharmony_ci node = con->list.next; 5262306a36Sopenharmony_ci if (node == head) 5362306a36Sopenharmony_ci goto done; 5462306a36Sopenharmony_ci next_con = container_of(node, struct hmdfs_peer, list); 5562306a36Sopenharmony_ci if (next_con->status == NODE_STAT_ONLINE) 5662306a36Sopenharmony_ci goto done; 5762306a36Sopenharmony_ci current_dev_id = next_con->device_id; 5862306a36Sopenharmony_ci next_con = NULL; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_cidone: 6262306a36Sopenharmony_ci if (next_con) 6362306a36Sopenharmony_ci peer_get(next_con); 6462306a36Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 6562306a36Sopenharmony_ci return next_con; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciint hmdfs_device_iterate(struct file *file, struct dir_context *ctx) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci int err = 0; 7162306a36Sopenharmony_ci uint64_t ino_start = DEVICE_VIEW_INO_START; 7262306a36Sopenharmony_ci struct hmdfs_peer *next_con = NULL; 7362306a36Sopenharmony_ci unsigned long dev_id = 0; 7462306a36Sopenharmony_ci struct hmdfs_peer *con = NULL; 7562306a36Sopenharmony_ci char *remote_device_name = NULL; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (ctx->pos != 0) 7862306a36Sopenharmony_ci goto out; 7962306a36Sopenharmony_ci dir_emit_dots(file, ctx); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (ctx->pos == LOCAL_DEVICE_CTX_POS) { 8262306a36Sopenharmony_ci err = dir_emit(ctx, DEVICE_VIEW_LOCAL, 8362306a36Sopenharmony_ci sizeof(DEVICE_VIEW_LOCAL) - 1, ino_start++, 8462306a36Sopenharmony_ci DT_DIR); 8562306a36Sopenharmony_ci if (!err) 8662306a36Sopenharmony_ci goto out; 8762306a36Sopenharmony_ci (ctx->pos)++; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (ctx->pos == CLOUD_DEVICE_CTX_POS) { 9162306a36Sopenharmony_ci err = dir_emit(ctx, DEVICE_VIEW_CLOUD, 9262306a36Sopenharmony_ci sizeof(DEVICE_VIEW_CLOUD) - 1, ino_start++, 9362306a36Sopenharmony_ci DT_DIR); 9462306a36Sopenharmony_ci if (!err) 9562306a36Sopenharmony_ci goto out; 9662306a36Sopenharmony_ci (ctx->pos)++; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci next_con = get_next_con(file->f_inode->i_sb->s_fs_info, 0); 10062306a36Sopenharmony_ci if (!next_con) 10162306a36Sopenharmony_ci goto out; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci dev_id = next_con->device_id; 10462306a36Sopenharmony_ci peer_put(next_con); 10562306a36Sopenharmony_ci con = hmdfs_lookup_from_devid(file->f_inode->i_sb->s_fs_info, dev_id); 10662306a36Sopenharmony_ci remote_device_name = kmalloc(HMDFS_CID_SIZE + 1, GFP_KERNEL); 10762306a36Sopenharmony_ci if (!remote_device_name) { 10862306a36Sopenharmony_ci err = -ENOMEM; 10962306a36Sopenharmony_ci goto out; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci while (con) { 11262306a36Sopenharmony_ci peer_put(con); 11362306a36Sopenharmony_ci snprintf(remote_device_name, HMDFS_CID_SIZE + 1, "%s", 11462306a36Sopenharmony_ci con->cid); 11562306a36Sopenharmony_ci if (!dir_emit(ctx, remote_device_name, 11662306a36Sopenharmony_ci strlen(remote_device_name), ino_start++, DT_DIR)) 11762306a36Sopenharmony_ci goto done; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci (ctx->pos)++; 12062306a36Sopenharmony_ci con = get_next_con(file->f_inode->i_sb->s_fs_info, dev_id); 12162306a36Sopenharmony_ci if (!con) 12262306a36Sopenharmony_ci goto done; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci dev_id = con->device_id; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_cidone: 12762306a36Sopenharmony_ci kfree(remote_device_name); 12862306a36Sopenharmony_ciout: 12962306a36Sopenharmony_ci if (err <= 0) 13062306a36Sopenharmony_ci ctx->pos = -1; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return err; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint hmdfs_root_iterate(struct file *file, struct dir_context *ctx) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci uint64_t ino_start = ROOT_DIR_INO_START; 13862306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = file_inode(file)->i_sb->s_fs_info; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (!dir_emit_dots(file, ctx)) 14162306a36Sopenharmony_ci return 0; 14262306a36Sopenharmony_ci if (ctx->pos == DEVICE_VIEW_CTX_POS) { 14362306a36Sopenharmony_ci if (!dir_emit(ctx, DEVICE_VIEW_ROOT, 14462306a36Sopenharmony_ci sizeof(DEVICE_VIEW_ROOT) - 1, ino_start, DT_DIR)) 14562306a36Sopenharmony_ci return 0; 14662306a36Sopenharmony_ci ino_start++; 14762306a36Sopenharmony_ci ctx->pos = MERGE_VIEW_CTX_POS; 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci if (sbi->s_merge_switch && ctx->pos == MERGE_VIEW_CTX_POS) { 15062306a36Sopenharmony_ci if (!dir_emit(ctx, MERGE_VIEW_ROOT, sizeof(MERGE_VIEW_ROOT) - 1, 15162306a36Sopenharmony_ci ino_start, DT_DIR)) 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci ino_start++; 15462306a36Sopenharmony_ci (ctx->pos)++; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci if (sbi->s_merge_switch && ctx->pos == CLOUD_MERGE_VIEW_CTX_POS) { 15762306a36Sopenharmony_ci if (!dir_emit(ctx, CLOUD_MERGE_VIEW_ROOT, sizeof(CLOUD_MERGE_VIEW_ROOT) - 1, 15862306a36Sopenharmony_ci ino_start, DT_DIR)) 15962306a36Sopenharmony_ci return 0; 16062306a36Sopenharmony_ci ino_start++; 16162306a36Sopenharmony_ci (ctx->pos)++; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci return 0; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciconst struct file_operations hmdfs_root_fops = { 16762306a36Sopenharmony_ci .owner = THIS_MODULE, 16862306a36Sopenharmony_ci .iterate_shared = hmdfs_root_iterate, 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciconst struct file_operations hmdfs_device_fops = { 17262306a36Sopenharmony_ci .owner = THIS_MODULE, 17362306a36Sopenharmony_ci .iterate_shared = hmdfs_device_iterate, 17462306a36Sopenharmony_ci}; 175