7
* Copyright (C) 1999, 2000 Richard Guenther
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
/* There are some generic issues for an implementation of the
26
* swapfile API to make it efficient for the desired tasks:
27
* - blocks need to be able to be shared between files
28
* - blocks need to be able to be split and continue to be
29
* shared between files
30
* Those requirements result in the following difficulties
31
* an implementation will run into:
32
* - maintaining a simple bitmask of unallocated blocks is not
33
* possible, as blocks may be shared, i.e. sort of an usage
34
* count is needed, not just a true/false state
35
* - mmapping a file is usually not (efficient) possible - only
36
* one block at a time can be mmapped due to block splitting
37
* block start offsets are not aligned to a minimum block size
38
* and block sizes are not multiples of a minimum block size
39
* - organizing files block allocation table as a simple linear
40
* list or as extends is not efficient because of the same
41
* block alignment/size issues, so a tree-like structure needs
42
* to be used for this - and in this tree the size of the blocks
43
* or their offsets in the file need to be stored
44
* - because of the splitting requirement one need information
45
* about which files use a given block - i.e. a reverse block
46
* allocation table needs to be maintained (optimize for the
47
* single file case, O(n) operations are acceptable)
48
* So an efficient implementation with respect to speed _and_
49
* storage requirement for metadata is quite difficult.
52
#include <sys/types.h>
60
typedef long swfd_t; /* open file cookie, like fd/FILE */
61
typedef struct { int dummy; } SWDIR; /* cookie for open directory, like DIR */
64
long name; /* file name */
65
size_t size; /* file size in bytes */
66
int mode; /* active protection */
67
off_t offset; /* current file pointer position */
68
off_t cluster_start; /* start of current cluster */
69
off_t cluster_end; /* end of current cluster */
70
size_t cluster_size; /* size of current cluster */
80
/**********************************************************************
81
* Initialization/cleanup
84
/* Registers a handler that gets executed if the swapfile subsystem
85
* is about to commit suicide. The message may be a hint to the user. */
86
void swapfile_register_panic_handler(void (*handler)(const char *));
88
/* Tries to open an existing swap file/partition.
89
* Returns 0 on success, -1 on failure.
91
* - missing swap file/parition
94
int swapfile_open(const char *name, int flags);
96
/* Syncs the in memory caches and metadata to disk. Does not sync
97
* exisiting memory mappings. */
100
/* Closes and updates a previously opened swap file/partition
101
* and marks it clean. */
102
void swapfile_close();
104
/* Tries to create an empty swapfile on name of size size. */
105
int swapfile_creat(const char *name, size_t size);
107
/* Tries to recover from unclean shutdown. Returns -1, if fsck
108
* cannot be performed or failed, 0 if swapfile is clean, 1 if
109
* swapfile was modified. Provide force == 1 to force a complete
110
* fsck, even if swapfile is clean. */
111
int swapfile_fsck(const char *name, int force);
115
/**********************************************************************
116
* Operations on the swapfile namespace. Unlike a unix filesystem
117
* the swapfile filesystem has names composed out of a single "long".
118
* Also the swapfile name hierarchy is flat - i.e. no directories.
119
* Names are >=0, negative values are reserved.
120
* All namespace operations are atomic (i.e. thread safe) and not
121
* undoable (well - just sw_unlink is not undoable).
124
/* Deletes a name from the filesystem. Like unlink(2). */
125
int sw_unlink(long name);
127
/* Open the (flat) swapfile directory for reading. The stream
128
* is positioned at the first file. Like opendir(3), but w/o
129
* directory specification for obvious reason. */
132
/* As the namespace is rather simple the equivalent to readdir(3) is
133
* just returning the names, no directory entry. Anything else
134
* is like readdir(3). If no further entries are available, -1 is returned. */
135
long sw_readdir(SWDIR *dir);
137
/* Like closedir(3). */
138
int sw_closedir(SWDIR *d);
141
/**********************************************************************
142
* Operations on a single file. Files are organized in variable sized
143
* clusters. Access to the file is limited to mapping those clusters.
146
/* Open a file like open(2) - flags can be O_CREAT, O_EXCL,
147
* O_RDWR, O_RDONLY, O_WRONLY with same semantics as open(2).
148
* Returns a file descriptor on success, -1 on error. */
149
swfd_t sw_open(long name, int flags);
151
/* Closes a file descriptor. Like close(2). */
152
int sw_close(swfd_t fd);
154
/* Changes the size of the file fd like ftruncate(2). */
155
int sw_ftruncate(swfd_t fd, off_t length);
157
/* Tries to copy count bytes from the current position of in_fd
158
* to the current position of out_fd (updating both file pointer
159
* positions). The actual number of copied bytes is returned, or
161
* Two different modes are supported (may be or'ed together):
162
* - SWSENDFILE_INSERT inserts into, rather than overwrites/extends
163
* the destination file
164
* - SWSENDFILE_CUT removes copied data from the source file
165
* The destination file descriptor may be SW_NOFILE, in that case
166
* no data is actually written (useful with SWSENDFILE_CUT). */
167
#define SW_NOFILE ((swfd_t)-1)
168
#define SWSENDFILE_INSERT 1
169
#define SWSENDFILE_CUT 2
170
ssize_t sw_sendfile(swfd_t out_fd, swfd_t in_fd, size_t count, int mode);
172
/* Update the file pointer position like lseek(2). */
173
off_t sw_lseek(swfd_t fd, off_t offset, int whence);
175
/* Like read(2), read count bytes from the current filepointer
176
* position to the array pointed to by buf. */
177
ssize_t sw_read(swfd_t fd, void *buf, size_t count);
179
/* Like write(2), write count bytes from buf starting at the current
180
* filepointer position. */
181
ssize_t sw_write(swfd_t fd, const void *buf, size_t count);
183
/* Obtain information about the file - works like fstat(2), but
184
* with different struct stat. Also included is information about
185
* the actual (file pointer position, see sw_lseek) cluster which
186
* can be mapped using sw_mmap. */
187
int sw_fstat(swfd_t fd, struct sw_stat *buf);
189
/* Maps the actual (file pointer position, see sw_lseek and sw_fstat)
190
* cluster into memory with parameters like mmap(2) - no size/offset
191
* as they are determined by the actual cluster offset/size. */
192
void *sw_mmap(void *start, int prot, int flags, swfd_t fd);
194
/* Unmaps a previously mapped part of a file. Like munmap(2). */
195
int sw_munmap(void *start);