libjio.h | libjio.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
/* Check if we're using Large File Support - otherwise refuse to build. | /* Check if we're using Large File Support - otherwise refuse to build. | |||
* Otherwise, we would allow applications not using LFS to link with the | * Otherwise, we would allow applications not using LFS to link with the | |||
* library (which uses LFS) and that's just begging for problems. There sho uld | * library (which uses LFS) and that's just begging for problems. There sho uld | |||
* be a portable way for the C library to do some of this for us, but until I | * be a portable way for the C library to do some of this for us, but until I | |||
* find one, this is the best we can do */ | * find one, this is the best we can do */ | |||
#ifndef _LARGEFILE_SOURCE | #ifndef _LARGEFILE_SOURCE | |||
#error "You must compile your application with Large File Support" | #error "You must compile your application with Large File Support" | |||
#endif | #endif | |||
/* logical structures */ | /* | |||
* Opaque types, the API does not expose these | ||||
/* the main file structure */ | */ | |||
struct jfs { | ||||
int fd; /* main file descriptor */ | ||||
char *name; /* and its name */ | ||||
char *jdir; /* journal directory */ | ||||
int jdirfd; /* journal directory file descriptor */ | ||||
int jfd; /* journal's lock file descriptor */ | ||||
unsigned int *jmap; /* journal's lock file mmap area */ | ||||
uint32_t flags; /* journal flags */ | ||||
struct jlinger *ltrans; /* lingered transactions */ | ||||
pthread_mutex_t ltlock; /* lingered transactions' lock */ | ||||
pthread_mutex_t lock; /* a soft lock used in some operations */ | ||||
}; | ||||
/* a single operation */ | /** An open file, similar to a file descriptor. */ | |||
struct joper { | typedef struct jfs jfs_t; | |||
int locked; /* is the region is locked? */ | ||||
off_t offset; /* operation's offset */ | ||||
size_t len; /* data length */ | ||||
void *buf; /* data */ | ||||
size_t plen; /* previous data length */ | ||||
void *pdata; /* previous data */ | ||||
struct joper *prev; | ||||
struct joper *next; | ||||
}; | ||||
/* a transaction */ | /** A single transaction. */ | |||
struct jtrans { | typedef struct jtrans jtrans_t; | |||
struct jfs *fs; /* journal file structure to operate on */ | ||||
char *name; /* name of the transaction file */ | ||||
int id; /* transaction id */ | ||||
uint32_t flags; /* transaction flags */ | ||||
unsigned int numops; /* quantity of operations in the list */ | ||||
ssize_t len; /* transaction's length */ | ||||
pthread_mutex_t lock; /* used to modify the operation list */ | ||||
struct joper *op; /* list of operations */ | ||||
}; | ||||
/* lingered transaction */ | /* | |||
struct jlinger { | * Public types | |||
int id; /* transaction id */ | */ | |||
char *name; /* name of the transaction file */ | ||||
struct jlinger *next; | ||||
}; | ||||
/** The result of a jfsck() run. | ||||
* | ||||
* @see jfsck() | ||||
* @ingroup check | ||||
*/ | ||||
struct jfsck_result { | struct jfsck_result { | |||
int total; /* total transactions files we looked at */ | /** Total transactions files processed */ | |||
int invalid; /* invalid files in the journal directory */ | int total; | |||
int in_progress; /* transactions in progress */ | ||||
int broken; /* transactions broken */ | ||||
int corrupt; /* corrupt transactions */ | ||||
int apply_error; /* errors applying the transaction */ | ||||
int reapplied; /* transactions that were reapplied */ | ||||
}; | ||||
/* on-disk structures */ | /** Number of invalid transactions */ | |||
int invalid; | ||||
/* header (fixed length, defined below) */ | /** Number of transactions in progress */ | |||
struct disk_header { | int in_progress; | |||
uint32_t id; /* id */ | ||||
uint32_t flags; /* flags about this transaction */ | /** Number of broken transactions */ | |||
uint32_t numops; /* number of operations */ | int broken; | |||
/** Number of corrupt transactions */ | ||||
int corrupt; | ||||
/** Number of errors applying transactions */ | ||||
int apply_error; | ||||
/** Number of transactions successfully reapplied */ | ||||
int reapplied; | ||||
}; | }; | |||
/* operation */ | /** jfsck() return values. | |||
struct disk_operation { | * | |||
uint32_t len; /* data length */ | * @see jfsck() | |||
uint32_t plen; /* previous data length */ | * @ingroup check | |||
uint64_t offset; /* offset relative to the BOF */ | */ | |||
char *prevdata; /* previous data for rollback */ | enum jfsck_return { | |||
/** Success */ | ||||
J_ESUCCESS = 0, | ||||
/** No such file or directory */ | ||||
J_ENOENT = -1, | ||||
/** No journal associated with the given file */ | ||||
J_ENOJOURNAL = -2, | ||||
/** Not enough free memory */ | ||||
J_ENOMEM = -3, | ||||
/** Error cleaning the journal directory */ | ||||
J_ECLEANUP = -4, | ||||
}; | }; | |||
/* core functions */ | /* | |||
int jopen(struct jfs *fs, const char *name, int flags, int mode, int jflags | * Core functions | |||
); | */ | |||
void jtrans_init(struct jfs *fs, struct jtrans *ts); | ||||
int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offs | ||||
et); | ||||
ssize_t jtrans_commit(struct jtrans *ts); | ||||
ssize_t jtrans_rollback(struct jtrans *ts); | ||||
void jtrans_free(struct jtrans *ts); | ||||
int jsync(struct jfs *fs); | ||||
int jmove_journal(struct jfs *fs, const char *newpath); | ||||
int jclose(struct jfs *fs); | ||||
/* journal checker */ | /** Open a file. | |||
int jfsck(const char *name, const char *jdir, struct jfsck_result *res); | * | |||
int jfsck_cleanup(const char *name, const char *jdir); | * Takes the same parameters as the UNIX open(2), with an additional one fo | |||
r | ||||
* internal flags. | ||||
* | ||||
* The only supported internal flag is J_LINGER, which enables lingering | ||||
* transactions. | ||||
* | ||||
* @param name path to the file to open | ||||
* @param flags flags to pass to open(2) | ||||
* @param mode mode to pass to open(2) | ||||
* @param jflags journal flags | ||||
* @returns a new jfs_t that identifies the open file on success, or NULL o | ||||
n | ||||
* error | ||||
* @see jclose(), open() | ||||
* @ingroup basic | ||||
*/ | ||||
jfs_t *jopen(const char *name, int flags, int mode, int jflags); | ||||
/* UNIX API wrappers */ | /** Close a file opened with jopen(). | |||
ssize_t jread(struct jfs *fs, void *buf, size_t count); | * | |||
ssize_t jpread(struct jfs *fs, void *buf, size_t count, off_t offset); | * After a call to this function, the memory allocated for the open file wi | |||
ssize_t jreadv(struct jfs *fs, const struct iovec *vector, int count); | ll | |||
ssize_t jwrite(struct jfs *fs, const void *buf, size_t count); | * be freed. | |||
ssize_t jpwrite(struct jfs *fs, const void *buf, size_t count, off_t offset | * | |||
); | * If there was an autosync thread started for this file, it will be stoppe | |||
ssize_t jwritev(struct jfs *fs, const struct iovec *vector, int count); | d. | |||
int jtruncate(struct jfs *fs, off_t length); | * | |||
off_t jlseek(struct jfs *fs, off_t offset, int whence); | * @param fs open file | |||
* @returns 0 on success, -1 on error | ||||
* @see jopen(), jfs_autosync_start() | ||||
* @ingroup basic | ||||
*/ | ||||
int jclose(jfs_t *fs); | ||||
/* ANSI C stdio wrappers */ | /** Sync a file. Makes sense only when using lingering transactions. | |||
struct jfs *jfopen(const char *path, const char *mode); | * | |||
int jfclose(struct jfs *stream); | * @param fs open file | |||
struct jfs *jfreopen(const char *path, const char *mode, struct jfs *stream | * @returns 0 on success, -1 on error | |||
); | * @ingroup basic | |||
size_t jfread(void *ptr, size_t size, size_t nmemb, struct jfs *stream); | */ | |||
size_t jfwrite(const void *ptr, size_t size, size_t nmemb, struct jfs *stre | int jsync(jfs_t *fs); | |||
am); | ||||
int jfileno(struct jfs *stream); | ||||
int jfeof(struct jfs *stream); | ||||
void jclearerr(struct jfs *stream); | ||||
int jferror(struct jfs *stream); | ||||
int jfseek(struct jfs *stream, long offset, int whence); | ||||
long jftell(struct jfs *stream); | ||||
void jrewind(struct jfs *stream); | ||||
FILE *jfsopen(struct jfs *stream, const char *mode); | ||||
/* jfs and jtrans constants */ | /** Create a new transaction. | |||
#define J_NOLOCK 1 /* don't lock the file before operating on i | * | |||
t */ | * @param fs open file the transaction will apply to | |||
#define J_NOROLLBACK 2 /* no need to read rollback information */ | * @returns a new transaction (must be freed using jtrans_free()) | |||
#define J_LINGER 4 /* use lingering transactions */ | * @see jtrans_free() | |||
#define J_COMMITTED 8 /* mark a transaction as committed */ | * @ingroup basic | |||
#define J_ROLLBACKED 16 /* mark a transaction as rollbacked */ | */ | |||
#define J_ROLLBACKING 32 /* mark a transaction as rollbacking */ | jtrans_t *jtrans_new(jfs_t *fs); | |||
#define J_RDONLY 64 /* mark a file as read-only */ | ||||
/* disk constants */ | /** Add an operation to a transaction. | |||
#define J_DISKHEADSIZE 12 /* length of disk_header */ | * | |||
#define J_DISKOPHEADSIZE 16 /* length of disk_operation header */ | * An operation consists of a buffer, its length, and the offset to write i | |||
t | ||||
* to. | ||||
* | ||||
* The file will not be touched (not even locked) until commit time, where | ||||
the | ||||
* first count bytes of buf will be written at offset. | ||||
* | ||||
* Transactions will be applied in order, and overlapping operations are | ||||
* permitted, in which case the latest one will prevail. | ||||
* | ||||
* @param ts transaction | ||||
* @param buf buffer to write | ||||
* @param count how many bytes from the buffer to write | ||||
* @param offset offset to write at | ||||
* @returns 0 on success, -1 on error | ||||
* @ingroup basic | ||||
*/ | ||||
int jtrans_add(jtrans_t *ts, const void *buf, size_t count, off_t offset); | ||||
/* jfsck constants (return values) */ | /** Commit a transaction. | |||
#define J_ESUCCESS 0 /* success - shouldn't be used */ | * | |||
#define J_ENOENT -1 /* no such file */ | * All the operations added to it using jtrans_add() will be written to dis | |||
#define J_ENOJOURNAL -2 /* no journal associated */ | k, | |||
#define J_ENOMEM -3 /* no enough free memory */ | * in the same order they were added. | |||
* | ||||
* After this function returns successfully, all the data can be trusted to | ||||
be | ||||
* on the disk. The commit is atomic with regards to other processes using | ||||
* libjio, but not accessing directly to the file. | ||||
* | ||||
* @param ts transaction | ||||
* @returns the amount of bytes written to disk, or -1 if there was an erro | ||||
r | ||||
* but atomic warranties were preserved, or -2 if there was an error an | ||||
d | ||||
* there is a possible break of atomic warranties (which is an indicati | ||||
on | ||||
* of a severe underlying condition). | ||||
* @ingroup basic | ||||
*/ | ||||
ssize_t jtrans_commit(jtrans_t *ts); | ||||
/** Rollback a transaction. | ||||
* | ||||
* This function atomically undoes a previous committed transaction. After | ||||
its | ||||
* successful return, the data can be trusted to be on disk. | ||||
* | ||||
* Use with care. | ||||
* | ||||
* @param ts transaction | ||||
* @returns the same as jtrans_commit() | ||||
* @see jtrans_commit() | ||||
* @ingroup basic | ||||
*/ | ||||
ssize_t jtrans_rollback(jtrans_t *ts); | ||||
/** Free a transaction structure. | ||||
* | ||||
* @param ts transaction to free | ||||
* @see jtrans_new() | ||||
* @ingroup basic | ||||
*/ | ||||
void jtrans_free(jtrans_t *ts); | ||||
/** Change the location of the journal directory. | ||||
* | ||||
* The file MUST NOT be in use by any other thread or process. The older | ||||
* journal directory will be removed. | ||||
* | ||||
* @param fs open file | ||||
* @param newpath path to the new journal directory, which will be created | ||||
if | ||||
* it doesn't exist | ||||
* @returns 0 on success, -1 on error | ||||
* @ingroup basic | ||||
*/ | ||||
int jmove_journal(jfs_t *fs, const char *newpath); | ||||
/* | ||||
* Autosync | ||||
*/ | ||||
/** Start an autosync thread. | ||||
* | ||||
* The thread will call jsync(fs) every max_sec seconds, or every max_bytes | ||||
* have been written. Only one autosync thread per open file is allowed. | ||||
* | ||||
* @param fs open file | ||||
* @param max_sec maximum number of seconds that should pass between each | ||||
* call to jsync() | ||||
* @param max_bytes maximum number of bytes that should be written between | ||||
* each call to jsync() | ||||
* @returns 0 on success, -1 on error | ||||
* @ingroup basic | ||||
*/ | ||||
int jfs_autosync_start(jfs_t *fs, time_t max_sec, size_t max_bytes); | ||||
/** Stop an autosync thread that was started using jfs_autosync_start(fs). | ||||
* | ||||
* @param fs open file | ||||
* @returns 0 on success, -1 on error | ||||
* @ingroup basic | ||||
*/ | ||||
int jfs_autosync_stop(jfs_t *fs); | ||||
/* | ||||
* Journal checker | ||||
*/ | ||||
/** Check and repair the given path. | ||||
* | ||||
* The file MUST NOT be in use by any other thread or process. This | ||||
* requirement will be lifted in future releases. | ||||
* | ||||
* @param name path to the file to check | ||||
* @param jdir journal directory of the given file, use NULL for the defaul | ||||
t | ||||
* @param res structure where to store the result | ||||
* @param flags flags that change the checking behaviour, currently only | ||||
* J_NOCLEANUP is supported, which avoids cleaning up the journal | ||||
* directory after a successful recovery | ||||
* @see struct jfsck_result | ||||
* @returns 0 on success, < 0 on error, with the following possible negativ | ||||
e | ||||
* values from enum jfsck_return: J_ENOENT if there was no such file wi | ||||
th | ||||
* the given name, J_ENOJOURNAL if there was no journal at the given | ||||
* jdir, J_ENOMEM if memory could not be allocated, J_ECLEANUP if there | ||||
* was an error cleaning the journal. | ||||
* @ingroup check | ||||
*/ | ||||
enum jfsck_return jfsck(const char *name, const char *jdir, | ||||
struct jfsck_result *res, unsigned int flags); | ||||
/* | ||||
* UNIX API wrappers | ||||
*/ | ||||
/** Read from the file. Works just like UNIX read(2). | ||||
* | ||||
* @param fs file to read from | ||||
* @param buf buffer used to store the data | ||||
* @param count maximum number of bytes to read | ||||
* @returns number of bytes read on success, or -1 on error | ||||
* @see read(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jread(jfs_t *fs, void *buf, size_t count); | ||||
/** Read from the file at the given offset. Works just like UNIX pread(2). | ||||
* | ||||
* @param fs file to read from | ||||
* @param buf buffer used to store the data | ||||
* @param count maximum number of bytes to read | ||||
* @param offset offset to read at | ||||
* @returns number of bytes read on success, or -1 on error | ||||
* @see pread(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jpread(jfs_t *fs, void *buf, size_t count, off_t offset); | ||||
/** Read from the file into multiple buffers. Works just like UNIX readv(2) | ||||
. | ||||
* | ||||
* @param fs file to read from | ||||
* @param vector buffers used to store the data | ||||
* @param count maximum number of bytes to read | ||||
* @returns number of bytes read on success, or -1 on error | ||||
* @see readv(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jreadv(jfs_t *fs, const struct iovec *vector, int count); | ||||
/** Write to the file. Works just like UNIX write(2). | ||||
* | ||||
* @param fs file to write to | ||||
* @param buf buffer used to read the data from | ||||
* @param count maximum number of bytes to write | ||||
* @returns number of bytes written on success, or -1 on error | ||||
* @see write(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jwrite(jfs_t *fs, const void *buf, size_t count); | ||||
/** Write to the file at the given offset. Works just like UNIX pwrite(2). | ||||
* | ||||
* @param fs file to write to | ||||
* @param buf buffer used to read the data from | ||||
* @param count maximum number of bytes to write | ||||
* @param offset offset to write at | ||||
* @returns number of bytes written on success, or -1 on error | ||||
* @see pwrite(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jpwrite(jfs_t *fs, const void *buf, size_t count, off_t offset); | ||||
/** Write to the file from multiple buffers. Works just like UNIX writev(2) | ||||
. | ||||
* | ||||
* @param fs file to write to | ||||
* @param vector buffers used to read the data from | ||||
* @param count maximum number of bytes to write | ||||
* @returns number of bytes written on success, or -1 on error | ||||
* @see writev(2) | ||||
* @ingroup unix | ||||
*/ | ||||
ssize_t jwritev(jfs_t *fs, const struct iovec *vector, int count); | ||||
/** Truncates the file to the given length. Works just like UNIX ftruncate( | ||||
2). | ||||
* | ||||
* @param fs file to truncate | ||||
* @param length lenght to truncate to | ||||
* @returns 0 on success, -1 on error | ||||
* @see ftruncate(2) | ||||
* @ingroup unix | ||||
*/ | ||||
int jtruncate(jfs_t *fs, off_t length); | ||||
/** Reposition read/write file offset. Works just like UNIX lseek(2). | ||||
* | ||||
* @param fs file to change the offset to | ||||
* @param offset offset to set | ||||
* @param whence where to count offset from, can be SEEK_SET to count from | ||||
the | ||||
* beginning of the file, SEEK_CUR to count from the current position, | ||||
or | ||||
* SEEK_END to count from the end. | ||||
* @returns the new offset counted from the beginning of the file, or -1 on | ||||
* error. | ||||
* @ingroup unix | ||||
*/ | ||||
off_t jlseek(jfs_t *fs, off_t offset, int whence); | ||||
/* | ||||
* ANSI C stdio wrappers | ||||
*/ | ||||
jfs_t *jfopen(const char *path, const char *mode); | ||||
int jfclose(jfs_t *stream); | ||||
jfs_t *jfreopen(const char *path, const char *mode, jfs_t *stream); | ||||
size_t jfread(void *ptr, size_t size, size_t nmemb, jfs_t *stream); | ||||
size_t jfwrite(const void *ptr, size_t size, size_t nmemb, jfs_t *stream); | ||||
int jfileno(jfs_t *stream); | ||||
int jfeof(jfs_t *stream); | ||||
void jclearerr(jfs_t *stream); | ||||
int jferror(jfs_t *stream); | ||||
int jfseek(jfs_t *stream, long offset, int whence); | ||||
long jftell(jfs_t *stream); | ||||
void jrewind(jfs_t *stream); | ||||
FILE *jfsopen(jfs_t *stream, const char *mode); | ||||
/* | ||||
* jopen() flags. | ||||
* | ||||
* Internally used also for jtrans_t flags. | ||||
*/ | ||||
/** Don't lock the file before operating on it. | ||||
* | ||||
* @see jopen() | ||||
* @ingroup basic */ | ||||
#define J_NOLOCK 1 | ||||
/** No need to read rollback information. | ||||
* | ||||
* @see jopen() | ||||
* @ingroup basic */ | ||||
#define J_NOROLLBACK 2 | ||||
/** Use lingering transactions. | ||||
* | ||||
* @see jopen() | ||||
* @ingroup basic */ | ||||
#define J_LINGER 4 | ||||
/* Range 8-256 is reserved for future public use */ | ||||
/** Marks a file as read-only. | ||||
* | ||||
* For internal use only, automatically set when O_RDONLY is passed to | ||||
* jopen(). | ||||
* | ||||
* @internal */ | ||||
#define J_RDONLY 512 | ||||
/* | ||||
* jtrans_t flags. | ||||
* | ||||
* For internal use only, but must be in the same space as the jopen() flag | ||||
s. | ||||
*/ | ||||
/** Marks a transaction as committed. | ||||
* @internal */ | ||||
#define J_COMMITTED 1024 | ||||
/** Marks a transaction as rollbacked. | ||||
* @internal */ | ||||
#define J_ROLLBACKED 2048 | ||||
/** Marks a transaction as rollbacking. | ||||
* @internal */ | ||||
#define J_ROLLBACKING 4096 | ||||
/* | ||||
* jfsck() flags | ||||
*/ | ||||
/** Do not perform a journal cleanup. Used in jfsck(). | ||||
* | ||||
* @see jfsck() | ||||
* @ingroup check */ | ||||
#define J_NOCLEANUP 1 | ||||
#endif | #endif | |||
End of changes. 16 change blocks. | ||||
121 lines changed or deleted | 435 lines changed or added | |||