| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved. |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #ifndef EUFS_DAX_H |
| #define EUFS_DAX_H |
| |
| #include "euler.h" |
| |
| #define EUFS_FILE_BCNT_WITH_HEIGHT(h) \ |
| (1ULL << ((h)*EUFS_FILE_TREE_DEGREE_SHIFT)) |
| #define EUFS_PTR_CNT_SHIFT_PER_CACHELINE 3 |
| |
| #define EUFS_H2_INDEX_IN_L0(bidx) ((bidx) >> EUFS_FILE_TREE_DEGREE_SHIFT) |
| #define EUFS_H2_INDEX_IN_L1(bidx) ((bidx) & (EUFS_FILE_TREE_DEGREE - 1)) |
| #define EUFS_H2_IS_FREE_L1_SUBTREE(idx0, bcnt) \ |
| (((idx0) << EUFS_FILE_TREE_DEGREE_SHIFT) >= (bcnt)) |
| |
| #define EUFS_H3_INDEX_IN_L0(bidx) \ |
| ((bidx) >> (EUFS_FILE_TREE_DEGREE_SHIFT * 2)) |
| /* (bidx - (idx0 << (SHIFT * 2))) >> SHIFT */ |
| #define EUFS_H3_INDEX_IN_L1(idx0, bidx) \ |
| (((bidx) >> EUFS_FILE_TREE_DEGREE_SHIFT) - \ |
| ((idx0) << EUFS_FILE_TREE_DEGREE_SHIFT)) |
| #define EUFS_H3_INDEX_IN_L2(bidx) ((bidx) & (EUFS_FILE_TREE_DEGREE - 1)) |
| |
| #define EUFS_H3_IS_FREE_L2_SUBTREE(idx0, idx1, bcnt) \ |
| ((((idx0) << (EUFS_FILE_TREE_DEGREE_SHIFT * 2)) + \ |
| ((idx1) << EUFS_FILE_TREE_DEGREE_SHIFT)) >= (bcnt)) |
| #define EUFS_H3_IS_FREE_L1_SUBTREE(idx0, bcnt) \ |
| (((idx0) << (EUFS_FILE_TREE_DEGREE_SHIFT * 2)) >= (bcnt)) |
| |
| int eufs_alloc_blocks_btree(struct inode *inode, unsigned long start_block, |
| unsigned long num_blocks, int zero); |
| ssize_t eufs_file_read(struct file *filp, char __user *buf, size_t len, |
| loff_t *ppos); |
| ssize_t eufs_file_write(struct file *filp, const char __user *buf, |
| size_t len, loff_t *ppos); |
| int eufs_dax_file_mmap(struct file *file, struct vm_area_struct *vma); |
| |
| int eufs_extend_btree(struct inode *inode, unsigned long num_blocks); |
| |
| int eufs_shrink_btree(struct inode *inode); |
| |
| static __always_inline u64 encode_root(u64 off, u64 height) |
| { |
| return (off & ((1UL << 56) - 1)) | (height << 56); |
| } |
| |
| static __always_inline u64 root_ptr(u64 encoded_root) |
| { |
| return (u64)(encoded_root & ((0x1UL << 56) - 1)); |
| } |
| static __always_inline int root_height(u64 ptr) |
| { |
| return ((u64)ptr >> 56) & 0xff; |
| } |
| |
| int eufs_free_btree(struct super_block *sb, void *root, int height, |
| u64 blocks); |
| int eufs_persist_btree(struct super_block *sb, void *root, int height, |
| u64 old_size, u64 new_size); |
| |
| ssize_t __eufs_file_write(struct address_space *mapping, |
| const char __user *buf, size_t count, loff_t pos, |
| loff_t *ppos, bool zero, bool keep); |
| ssize_t __eufs_file_write_inode(struct inode *inode, |
| const char __user *buf, size_t count, |
| loff_t pos, loff_t *ppos, bool zero, |
| bool keep); |
| |
| loff_t eufs_file_llseek(struct file *file, loff_t offset, int whence); |
| |
| /* zeroing range [pos, end) */ |
| static inline void eufs_inode_zero_range(struct inode *inode, loff_t pos, |
| loff_t end) |
| { |
| if (pos == end) |
| return; |
| __eufs_file_write_inode(inode, NULL, end - pos, pos, NULL, true, |
| true); |
| } |
| /* zeroing range [pos, end) */ |
| static inline void eufs_inode_zero_range_len(struct inode *inode, loff_t pos, |
| size_t len) |
| { |
| if (!len) |
| return; |
| __eufs_file_write_inode(inode, NULL, len, pos, NULL, true, true); |
| } |
| |
| #endif /* EUFS_DAX_H */ |