forked from WiscADSL/MadFS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.h
136 lines (115 loc) · 3.78 KB
/
file.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#pragma once
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <tbb/concurrent_unordered_map.h>
#include <cstdint>
#include <ctime>
#include <iostream>
#include <stdexcept>
#include "alloc/alloc.h"
#include "bitmap.h"
#include "blk_table.h"
#include "block/block.h"
#include "config.h"
#include "const.h"
#include "entry.h"
#include "idx.h"
#include "mem_table.h"
#include "offset.h"
#include "posix.h"
#include "shm.h"
#include "tx/lock.h"
#include "utils/utils.h"
namespace madfs::utility {
class Converter;
} // namespace madfs::utility
// data structure under this namespace must be in volatile memory (DRAM)
namespace madfs::dram {
class File {
public:
BitmapMgr bitmap_mgr;
MemTable mem_table;
OffsetMgr offset_mgr;
BlkTable blk_table;
ShmMgr shm_mgr;
pmem::MetaBlock* const meta;
Lock lock; // nop lock is used by default
const char* path; // only set at debug mode
int fd; // only used in destructor, can set to -1 to prevent close
const bool can_read;
const bool can_write;
private:
// each thread tid has its local allocator
// the allocator is a per-thread per-file data structure
tbb::concurrent_unordered_map<pid_t, Allocator> allocators;
public:
File(int fd, const struct stat& stat, int flags, const char* pathname);
~File();
/*
* POSIX I/O operations
*/
ssize_t pwrite(const char* buf, size_t count, size_t offset);
ssize_t write(const char* buf, size_t count);
ssize_t pread(char* buf, size_t count, size_t offset);
ssize_t read(char* buf, size_t count);
off_t lseek(off_t offset, int whence);
void* mmap(void* addr, size_t length, int prot, int flags,
size_t offset) const;
int fsync();
void stat(struct stat* buf) {
buf->st_size = static_cast<off_t>(blk_table.update_unsafe());
}
[[nodiscard]] Allocator* get_local_allocator() {
if (auto it = allocators.find(tid); it != allocators.end()) {
return &it->second;
}
auto [it, ok] = allocators.emplace(
std::piecewise_construct, std::forward_as_tuple(tid),
std::forward_as_tuple(&mem_table, &bitmap_mgr,
shm_mgr.alloc_per_thread_data()));
PANIC_IF(!ok, "insert to thread-local allocators failed");
return &it->second;
}
// try to open a file with checking whether the given file is in MadFS format
static bool try_open(int& fd, struct stat& stat_buf, const char* pathname,
int flags, mode_t mode) {
TimerGuard<Event::OPEN_SYS> timer_guard;
if ((flags & O_ACCMODE) == O_WRONLY) {
LOG_INFO("File \"%s\" opened with O_WRONLY. Changed to O_RDWR.",
pathname);
flags &= ~O_WRONLY;
flags |= O_RDWR;
}
fd = posix::open(pathname, flags, mode);
if (unlikely(fd < 0)) {
LOG_WARN("File \"%s\" open failed: %m", pathname);
return false;
}
if (!(flags & O_CREAT)) {
// a non-empty file w/o shm_path cannot be a MadFS file
ssize_t rc = fgetxattr(fd, SHM_XATTR_NAME, nullptr, 0);
if (rc == -1) return false;
}
int rc = posix::fstat(fd, &stat_buf);
if (unlikely(rc < 0)) {
LOG_WARN("File \"%s\" fstat failed: %m. Fallback to syscall.", pathname);
return false;
}
// we don't handle non-normal file (e.g., socket, directory, block dev)
if (unlikely(!S_ISREG(stat_buf.st_mode) && !S_ISLNK(stat_buf.st_mode))) {
LOG_WARN("Non-normal file \"%s\". Fallback to syscall.", pathname);
return false;
}
if (!IS_ALIGNED(stat_buf.st_size, BLOCK_SIZE)) {
LOG_WARN("File size not aligned for \"%s\". Fallback to syscall",
pathname);
return false;
}
return true;
}
friend std::ostream& operator<<(std::ostream& out, File& f);
};
} // namespace madfs::dram