// SPDX-License-Identifier: GPL-2.0/* * dax: direct host memory access * Copyright (C) 2020 Red Hat, Inc. */#include"fuse_i.h"#include<linux/delay.h>#include<linux/dax.h>#include<linux/uio.h>#include<linux/pagemap.h>#include<linux/pfn_t.h>#include<linux/iomap.h>#include<linux/interval_tree.h>/* * Default memory range size. A power of 2 so it agrees with common FUSE_INIT * map_alignment values 4KB and 64KB. */#define FUSE_DAX_SHIFT 21#define FUSE_DAX_SZ (1 << FUSE_DAX_SHIFT)#define FUSE_DAX_PAGES (FUSE_DAX_SZ / PAGE_SIZE)/* Number of ranges reclaimer will try to free in one invocation */#define FUSE_DAX_RECLAIM_CHUNK (10)/* * Dax memory reclaim threshold in percetage of total ranges. When free * number of free ranges drops below this threshold, reclaim can trigger * Default is 20% */#define FUSE_DAX_RECLAIM_THRESHOLD (20)/** Translation information for file offsets to DAX window offsets */structfuse_dax_mapping{/* Pointer to inode where this memory range is mapped */structinode*inode;/* Will connect in fcd->free_ranges to keep track of free memory */structlist_headlist;/* For interval tree in file/inode */structinterval_tree_nodeitn;/* Will connect in fc->busy_ranges to keep track busy memory */structlist_headbusy_list;/** Position in DAX window */u64window_offset;/** Length of mapping, in bytes */loff_tlength;/* Is this mapping read-only or read-write */boolwritable;/* reference count when the mapping is used by dax iomap. */refcount_trefcnt;};/* Per-inode dax map */structfuse_inode_dax{/* Semaphore to protect modifications to the dmap tree */structrw_semaphoresem;/* Sorted rb tree of struct fuse_dax_mapping elements */structrb_root_cachedtree;unsignedlongnr;};structfuse_conn_dax{/* DAX device */structdax_device*dev;/* Lock protecting accessess to members of this structure */spinlock_tlock;/* List of memory ranges which are busy */unsignedlongnr_busy_ranges;structlist_headbusy_ranges;/* Worker to free up memory ranges */structdelayed_workfree_work;/* Wait queue for a dax range to become free */wait_queue_head_trange_waitq;/* DAX Window Free Ranges */longnr_free_ranges;structlist_headfree_ranges;unsignedlongnr_ranges;};staticinlinestructfuse_dax_mapping*node_to_dmap(structinterval_tree_node*node){if(!node)returnNULL;return