1 /*
2    Copyright 2013-2014 EditShare, 2013-2015 Skytechnology sp. z o.o.
3 
4    This file is part of LizardFS.
5 
6    LizardFS is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, version 3.
9 
10    LizardFS is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with LizardFS. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 #include "common/platform.h"
21 
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include "common/chunk_with_address_and_label.h"
32 #include "common/exception.h"
33 #include "mount/group_cache.h"
34 #include "mount/lizard_client_context.h"
35 #include "mount/readdata_cache.h"
36 #include "mount/stat_defs.h"
37 #include "protocol/chunkserver_list_entry.h"
38 #include "protocol/lock_info.h"
39 #include "protocol/named_inode_entry.h"
40 
41 namespace LizardClient {
42 
43 typedef uint32_t Inode;
44 typedef uint32_t JobId;
45 typedef uint32_t NamedInodeOffset;
46 
47 struct FsInitParams {
48 	static constexpr const char *kDefaultSubfolder = "/";
49 	static constexpr bool     kDefaultDoNotRememberPassword = false;
50 	static constexpr bool     kDefaultDelayedInit = false;
51 #ifdef _WIN32
52 	static constexpr unsigned kDefaultReportReservedPeriod = 60;
53 #else
54 	static constexpr unsigned kDefaultReportReservedPeriod = 30;
55 #endif
56 	static constexpr unsigned kDefaultIoRetries = 30;
57 	static constexpr unsigned kDefaultRoundTime = 200;
58 	static constexpr unsigned kDefaultChunkserverConnectTo = 2000;
59 	static constexpr unsigned kDefaultChunkserverReadTo = 2000;
60 	static constexpr unsigned kDefaultChunkserverWaveReadTo = 500;
61 	static constexpr unsigned kDefaultChunkserverTotalReadTo = 2000;
62 	static constexpr unsigned kDefaultCacheExpirationTime = 300;
63 	static constexpr unsigned kDefaultReadaheadMaxWindowSize = 16384;
64 	static constexpr bool     kDefaultPrefetchXorStripes = false;
65 
66 	static constexpr float    kDefaultBandwidthOveruse = 1.0;
67 	static constexpr unsigned kDefaultChunkserverWriteTo = 5000;
68 #ifdef _WIN32
69 	static constexpr unsigned kDefaultWriteCacheSize = 50;
70 #else
71 	static constexpr unsigned kDefaultWriteCacheSize = 0;
72 #endif
73 	static constexpr unsigned kDefaultCachePerInodePercentage = 25;
74 	static constexpr unsigned kDefaultWriteWorkers = 10;
75 	static constexpr unsigned kDefaultWriteWindowSize = 15;
76 	static constexpr unsigned kDefaultSymlinkCacheTimeout = 3600;
77 
78 	static constexpr bool     kDefaultDebugMode = false;
79 	static constexpr int      kDefaultKeepCache = 0;
80 	static constexpr double   kDefaultDirentryCacheTimeout = 0.25;
81 	static constexpr unsigned kDefaultDirentryCacheSize = 100000;
82 	static constexpr double   kDefaultEntryCacheTimeout = 0.0;
83 	static constexpr double   kDefaultAttrCacheTimeout = 1.0;
84 #ifdef __linux__
85 	static constexpr bool     kDefaultMkdirCopySgid = true;
86 #else
87 	static constexpr bool     kDefaultMkdirCopySgid = false;
88 #endif
89 #if defined(DEFAULT_SUGID_CLEAR_MODE_EXT)
90 	static constexpr SugidClearMode kDefaultSugidClearMode = SugidClearMode::kExt;
91 #elif defined(DEFAULT_SUGID_CLEAR_MODE_BSD)
92 	static constexpr SugidClearMode kDefaultSugidClearMode = SugidClearMode::kBsd;
93 #elif defined(DEFAULT_SUGID_CLEAR_MODE_OSX)
94 	static constexpr SugidClearMode kDefaultSugidClearMode = SugidClearMode::kOsx;
95 #else
96 	static constexpr SugidClearMode kDefaultSugidClearMode = SugidClearMode::kNever;
97 #endif
98 	static constexpr bool     kDefaultUseRwLock = true;
99 	static constexpr double   kDefaultAclCacheTimeout = 1.0;
100 	static constexpr unsigned kDefaultAclCacheSize = 1000;
101 	static constexpr bool     kDefaultVerbose = false;
102 
103 	// Thank you, GCC 4.6, for no delegating constructors
FsInitParamsFsInitParams104 	FsInitParams()
105 	             : bind_host(), host(), port(), meta(false), mountpoint(), subfolder(kDefaultSubfolder),
106 	             do_not_remember_password(kDefaultDoNotRememberPassword), delayed_init(kDefaultDelayedInit),
107 	             report_reserved_period(kDefaultReportReservedPeriod),
108 	             io_retries(kDefaultIoRetries),
109 	             chunkserver_round_time_ms(kDefaultRoundTime),
110 	             chunkserver_connect_timeout_ms(kDefaultChunkserverConnectTo),
111 	             chunkserver_wave_read_timeout_ms(kDefaultChunkserverWaveReadTo),
112 	             total_read_timeout_ms(kDefaultChunkserverTotalReadTo),
113 	             cache_expiration_time_ms(kDefaultCacheExpirationTime),
114 	             readahead_max_window_size_kB(kDefaultReadaheadMaxWindowSize),
115 	             prefetch_xor_stripes(kDefaultPrefetchXorStripes),
116 	             bandwidth_overuse(kDefaultBandwidthOveruse),
117 	             write_cache_size(kDefaultWriteCacheSize),
118 	             write_workers(kDefaultWriteWorkers), write_window_size(kDefaultWriteWindowSize),
119 	             chunkserver_write_timeout_ms(kDefaultChunkserverWriteTo),
120 	             cache_per_inode_percentage(kDefaultCachePerInodePercentage),
121 	             symlink_cache_timeout_s(kDefaultSymlinkCacheTimeout),
122 	             debug_mode(kDefaultDebugMode), keep_cache(kDefaultKeepCache),
123 	             direntry_cache_timeout(kDefaultDirentryCacheTimeout), direntry_cache_size(kDefaultDirentryCacheSize),
124 	             entry_cache_timeout(kDefaultEntryCacheTimeout), attr_cache_timeout(kDefaultAttrCacheTimeout),
125 	             mkdir_copy_sgid(kDefaultMkdirCopySgid), sugid_clear_mode(kDefaultSugidClearMode),
126 	             use_rw_lock(kDefaultUseRwLock),
127 	             acl_cache_timeout(kDefaultAclCacheTimeout), acl_cache_size(kDefaultAclCacheSize),
128 	             verbose(kDefaultVerbose) {
129 	}
130 
FsInitParamsFsInitParams131 	FsInitParams(const std::string &bind_host, const std::string &host, const std::string &port, const std::string &mountpoint)
132 	             : bind_host(bind_host), host(host), port(port), meta(false), mountpoint(mountpoint), subfolder(kDefaultSubfolder),
133 	             do_not_remember_password(kDefaultDoNotRememberPassword), delayed_init(kDefaultDelayedInit),
134 	             report_reserved_period(kDefaultReportReservedPeriod),
135 	             io_retries(kDefaultIoRetries),
136 	             chunkserver_round_time_ms(kDefaultRoundTime),
137 	             chunkserver_connect_timeout_ms(kDefaultChunkserverConnectTo),
138 	             chunkserver_wave_read_timeout_ms(kDefaultChunkserverWaveReadTo),
139 	             total_read_timeout_ms(kDefaultChunkserverTotalReadTo),
140 	             cache_expiration_time_ms(kDefaultCacheExpirationTime),
141 	             readahead_max_window_size_kB(kDefaultReadaheadMaxWindowSize),
142 	             prefetch_xor_stripes(kDefaultPrefetchXorStripes),
143 	             bandwidth_overuse(kDefaultBandwidthOveruse),
144 	             write_cache_size(kDefaultWriteCacheSize),
145 	             write_workers(kDefaultWriteWorkers), write_window_size(kDefaultWriteWindowSize),
146 	             chunkserver_write_timeout_ms(kDefaultChunkserverWriteTo),
147 	             cache_per_inode_percentage(kDefaultCachePerInodePercentage),
148 	             symlink_cache_timeout_s(kDefaultSymlinkCacheTimeout),
149 	             debug_mode(kDefaultDebugMode), keep_cache(kDefaultKeepCache),
150 	             direntry_cache_timeout(kDefaultDirentryCacheTimeout), direntry_cache_size(kDefaultDirentryCacheSize),
151 	             entry_cache_timeout(kDefaultEntryCacheTimeout), attr_cache_timeout(kDefaultAttrCacheTimeout),
152 	             mkdir_copy_sgid(kDefaultMkdirCopySgid), sugid_clear_mode(kDefaultSugidClearMode),
153 	             use_rw_lock(kDefaultUseRwLock),
154 	             acl_cache_timeout(kDefaultAclCacheTimeout), acl_cache_size(kDefaultAclCacheSize),
155 	             verbose(kDefaultVerbose) {
156 	}
157 
158 	std::string bind_host;
159 	std::string host;
160 	std::string port;
161 	bool meta;
162 	std::string mountpoint;
163 	std::string subfolder;
164 	std::vector<uint8_t> password_digest;
165 	bool do_not_remember_password;
166 	bool delayed_init;
167 	unsigned report_reserved_period;
168 
169 	unsigned io_retries;
170 	unsigned chunkserver_round_time_ms;
171 	unsigned chunkserver_connect_timeout_ms;
172 	unsigned chunkserver_wave_read_timeout_ms;
173 	unsigned total_read_timeout_ms;
174 	unsigned cache_expiration_time_ms;
175 	unsigned readahead_max_window_size_kB;
176 	bool prefetch_xor_stripes;
177 	double bandwidth_overuse;
178 
179 	unsigned write_cache_size;
180 	unsigned write_workers;
181 	unsigned write_window_size;
182 	unsigned chunkserver_write_timeout_ms;
183 	unsigned cache_per_inode_percentage;
184 	unsigned symlink_cache_timeout_s;
185 
186 	bool debug_mode;
187 	// NOTICE(sarna): This variable can hold more values than 0-1, don't change it to bool ever.
188 	int keep_cache;
189 	double direntry_cache_timeout;
190 	unsigned direntry_cache_size;
191 	double entry_cache_timeout;
192 	double attr_cache_timeout;
193 	bool mkdir_copy_sgid;
194 	SugidClearMode sugid_clear_mode;
195 	bool use_rw_lock;
196 	double acl_cache_timeout;
197 	unsigned acl_cache_size;
198 
199 	bool verbose;
200 
201 	std::string io_limits_config_file;
202 };
203 
204 /**
205  * A class that is used for passing information between subsequent calls to the filesystem.
206  * It is created when a file is opened, updated with every use of the file descriptor and
207  * removed when a file is closed.
208  */
209 struct FileInfo {
FileInfoFileInfo210 	FileInfo() : flags(), direct_io(), keep_cache(), fh(), lock_owner() {}
211 
FileInfoFileInfo212 	FileInfo(int flags, unsigned int direct_io, unsigned int keep_cache, uint64_t fh,
213 		uint64_t lock_owner)
214 			: flags(flags),
215 			direct_io(direct_io),
216 			keep_cache(keep_cache),
217 			fh(fh),
218 			lock_owner(lock_owner) {
219 	}
220 
221 	FileInfo(const FileInfo &other) = default;
222 	FileInfo(FileInfo &&other) = default;
223 
224 	FileInfo &operator=(const FileInfo &other) = default;
225 	FileInfo &operator=(FileInfo &&other) = default;
226 
isValidFileInfo227 	bool isValid() const {
228 		return fh;
229 	}
230 
resetFileInfo231 	void reset() {
232 		*this = FileInfo();
233 	}
234 
235 	int flags;
236 	unsigned int direct_io : 1;
237 	unsigned int keep_cache : 1;
238 	uint64_t fh;
239 	uint64_t lock_owner;
240 };
241 
242 /**
243  * Directory entry parameters, a result of some filesystem operations (lookup, mkdir,
244  * link etc.).
245  */
246 struct EntryParam {
EntryParamEntryParam247 	EntryParam() : ino(0), generation(0), attr_timeout(0), entry_timeout(0) {
248 		memset(&attr, 0, sizeof(struct stat));
249 	}
250 
251 	Inode ino;
252 	unsigned long generation;
253 	struct stat attr;
254 	double attr_timeout;
255 	double entry_timeout;
256 };
257 
258 /**
259  * A result of setattr and getattr operations
260  */
261 struct AttrReply {
262 	struct stat attr;
263 	double attrTimeout;
264 };
265 
266 /**
267  * A result of readdir operation
268  */
269 struct DirEntry {
270 	std::string name;
271 	struct stat attr;
272 	off_t nextEntryOffset;
273 
DirEntryDirEntry274 	DirEntry(const std::string n, const struct stat &s, off_t o) : name(n), attr(s), nextEntryOffset(o) {}
275 };
276 
277 /**
278  * A result of getxattr, setxattr and listattr operations
279  */
280 struct XattrReply {
281 	uint32_t valueLength;
282 	std::vector<uint8_t> valueBuffer;
283 };
284 
285 /**
286  * An exception that is thrown when a request can't be executed successfully
287  */
288 struct RequestException : public std::exception {
289 	explicit RequestException(int error_code);
290 
291 	int system_error_code;
292 	int lizardfs_error_code;
293 };
294 
295 void updateGroups(Context &ctx);
296 
297 // TODO what about this one? Will decide when writing non-fuse client
298 // void fsinit(void *userdata, struct fuse_conn_info *conn);
299 bool isSpecialInode(LizardClient::Inode ino);
300 
301 EntryParam lookup(const Context &ctx, Inode parent, const char *name);
302 
303 AttrReply getattr(const Context &ctx, Inode ino);
304 
305 #define LIZARDFS_SET_ATTR_MODE      (1 << 0)
306 #define LIZARDFS_SET_ATTR_UID       (1 << 1)
307 #define LIZARDFS_SET_ATTR_GID       (1 << 2)
308 #define LIZARDFS_SET_ATTR_SIZE      (1 << 3)
309 #define LIZARDFS_SET_ATTR_ATIME     (1 << 4)
310 #define LIZARDFS_SET_ATTR_MTIME     (1 << 5)
311 #define LIZARDFS_SET_ATTR_ATIME_NOW (1 << 7)
312 #define LIZARDFS_SET_ATTR_MTIME_NOW (1 << 8)
313 AttrReply setattr(const Context &ctx, Inode ino, struct stat *stbuf, int to_set);
314 
315 std::string readlink(const Context &ctx, Inode ino);
316 
317 EntryParam mknod(const Context &ctx, Inode parent, const char *name, mode_t mode, dev_t rdev);
318 
319 EntryParam mkdir(const Context &ctx, Inode parent, const char *name, mode_t mode);
320 
321 void unlink(const Context &ctx, Inode parent, const char *name);
322 
323 void undel(const Context &ctx, Inode ino);
324 
325 void rmdir(const Context &ctx, Inode parent, const char *name);
326 
327 EntryParam symlink(const Context &ctx, const char *link, Inode parent, const char *name);
328 
329 void rename(const Context &ctx, Inode parent, const char *name, Inode newparent, const char *newname);
330 
331 EntryParam link(const Context &ctx, Inode ino, Inode newparent, const char *newname);
332 
333 void open(const Context &ctx, Inode ino, FileInfo* fi);
334 
335 std::vector<uint8_t> read_special_inode(const Context &ctx, Inode ino, size_t size, off_t off,
336 				        FileInfo* fi);
337 
338 ReadCache::Result read(const Context &ctx, Inode ino, size_t size, off_t off, FileInfo* fi);
339 
340 typedef size_t BytesWritten;
341 BytesWritten write(const Context &ctx, Inode ino, const char *buf, size_t size, off_t off,
342 		FileInfo* fi);
343 
344 void flush(const Context &ctx, Inode ino, FileInfo* fi);
345 
346 void release(Inode ino, FileInfo* fi);
347 
348 void fsync(const Context &ctx, Inode ino, int datasync, FileInfo* fi);
349 
350 void opendir(const Context &ctx, Inode ino);
351 
352 std::vector<DirEntry> readdir(const Context &ctx, Inode ino, off_t off, size_t max_entries);
353 
354 std::vector<NamedInodeEntry> readreserved(const Context &ctx, NamedInodeOffset offset, NamedInodeOffset max_entries);
355 
356 std::vector<NamedInodeEntry> readtrash(const Context &ctx, NamedInodeOffset offset, NamedInodeOffset max_entries);
357 
358 void releasedir(Inode ino);
359 
360 struct statvfs statfs(const Context &ctx, Inode ino);
361 
362 void setxattr(const Context &ctx, Inode ino, const char *name, const char *value,
363 		size_t size, int flags, uint32_t position);
364 
365 XattrReply getxattr(const Context &ctx, Inode ino, const char *name, size_t size, uint32_t position);
366 
367 XattrReply listxattr(const Context &ctx, Inode ino, size_t size);
368 
369 void removexattr(const Context &ctx, Inode ino, const char *name);
370 
371 void access(const Context &ctx, Inode ino, int mask);
372 
373 EntryParam create(const Context &ctx, Inode parent, const char *name,
374 		mode_t mode, FileInfo* fi);
375 
376 void getlk(const Context &ctx, Inode ino, FileInfo* fi, struct lzfs_locks::FlockWrapper &lock);
377 uint32_t setlk_send(const Context &ctx, Inode ino, FileInfo* fi, struct lzfs_locks::FlockWrapper &lock);
378 void setlk_recv();
379 uint32_t flock_send(const Context &ctx, Inode ino, FileInfo* fi, int op);
380 void flock_recv();
381 
382 void flock_interrupt(const lzfs_locks::InterruptData &data);
383 void setlk_interrupt(const lzfs_locks::InterruptData &data);
384 
385 void remove_file_info(FileInfo *f);
386 void remove_dir_info(FileInfo *f);
387 
388 JobId makesnapshot(const Context &ctx, Inode ino, Inode dst_parent, const std::string &dst_name,
389 	          bool can_overwrite);
390 std::string getgoal(const Context &ctx, Inode ino);
391 void setgoal(const Context &ctx, Inode ino, const std::string &goal_name, uint8_t smode);
392 
393 void statfs(uint64_t *totalspace, uint64_t *availspace, uint64_t *trashspace, uint64_t *reservedspace, uint32_t *inodes);
394 
395 std::vector<ChunkWithAddressAndLabel> getchunksinfo(const Context &ctx, Inode ino,
396 	                                                uint32_t chunk_index, uint32_t chunk_count);
397 
398 std::vector<ChunkserverListEntry> getchunkservers();
399 
400 void fs_init(FsInitParams &params);
401 void fs_term();
402 
403 }
404