file.h 6.58 KB
Newer Older
1 2 3 4
#ifndef _WENDELIN_BIGFILE_FILE_H_
#define _WENDELIN_BIGFILE_FILE_H_

/* Wendelin.bigfile | Base file class
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
5
 * Copyright (C) 2014-2020  Nexedi SA and Contributors.
6 7 8 9 10 11 12
 *                          Kirill Smelkov <kirr@nexedi.com>
 *
 * This program is free software: you can Use, Study, Modify and Redistribute
 * it under the terms of the GNU General Public License version 3, or (at your
 * option) any later version, as published by the Free Software Foundation.
 *
 * You can also Link and Combine this program with other software covered by
13 14 15 16
 * the terms of any of the Free Software licenses or any of the Open Source
 * Initiative approved licenses and Convey the resulting work. Corresponding
 * source of such a combination shall include the source code for all other
 * software used.
17 18 19 20 21
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See COPYING file for full licensing terms.
22
 * See https://www.nexedi.com/licensing for rationale and options.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
23 24 25 26
 */

/* Header wendelin/bigfile/file.h provides BigFile and interfaces that
 * particular BigFile implementations must provide.
27
 *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
28 29 30
 * The interfaces are described in `struct bigfile_ops`.
 * A particular BigFile implementation must provide loadblk/storeblk and
 * optionally mmap_* methods.
31
 *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
32 33
 * Clients work with bigfiles via mapping files to memory - see
 * wendelin/bigfile/virtmem.h and BigFileH for client-level API details.
34 35 36 37 38
 */

#include <stddef.h>
#include <wendelin/bigfile/types.h>

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
39 40 41 42
#ifdef __cplusplus
extern "C" {
#endif

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
43 44
typedef struct VMA VMA;

45 46 47 48

/* BigFile base class
 *
 * BigFile is a file of fixed size blocks. It knows how to load/store blocks
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
49
 * to/from memory. It can be also optionally memory mmaped.
50 51 52 53 54 55 56 57 58 59
 *
 * Concrete file implementations subclass BigFile and define their file_ops.
 */
struct BigFile {
    const struct bigfile_ops *file_ops;

    size_t blksize;     /* size of block */
};
typedef struct BigFile BigFile;

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
60
/* bigfile_ops defines interface that BigFile implementations must provide. */
61
struct bigfile_ops {
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
62
    /* loadblk is called to load file block into memory.
63
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
64 65 66
     * NOTE loadblk is called from SIGSEGV signal handler context.
     *
     * len(buf) must be = file->blksize.
67 68 69
     * @return  0 - ok      !0 - fail
     */
    int  (*loadblk)  (BigFile *file, blk_t blk, void *buf);
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
70 71 72 73 74 75 76 77

    /* storeblk is called to store file block from memory.
     *
     * NOTE contrary to loadblk, storeblk is called from regular context.
     *
     * len(buf) must be = file->blksize.
     * @return  0 - ok      !0 - fail
     */
78 79
    int  (*storeblk) (BigFile *file, blk_t blk, const void *buf);

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
80 81 82 83 84
    /* release is called to release resources associated with file.
     *
     * The file is not otherwise used at the time of and past release call.
     */
    void (*release)  (BigFile *file);
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
85

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
86

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
87 88 89 90 91 92 93 94 95 96
    /* Mmap overlaying
     *
     * Besides .loadblk and .storeblk a particular BigFile implementation can
     * also optionally provide functions to setup read-only memory mappings
     * with BigFile data. If such functions are provided, virtmem might use
     * them to organize read access to BigFile data through the mappings and
     * without allocating RAM for read pages. RAM will still be allocated for
     * dirtied pages that are layed over base data layer provided by the
     * mappings.
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
97 98 99
     * The primary user of this functionality is wcfs - virtual filesystem that
     * provides access to ZBigFile data via OS-level files(*). The layering can
     * be schematically depicted as follows
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
     *
     *                  ┌──┐                      ┌──┐
     *                  │RW│                      │RW│      ← dirty pages
     *                  └──┘                      └──┘
     *                            +
     *      ─────────────────────────────────────────────   ← mmap'ed base data
     *
     * The functions to setup memory mappings are:
     *
     *   - mmap_setup_read(vma, file[blk +blklen)) -> addr    setup initial read-only mmap to serve vma
     *   - remmap_blk_read(vma, file[blk])            remmap blk into vma again, after e.g.
     *                                                RW dirty page was discarded
     *   - munmap(vma)                                before VMA is unmapped
     *
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
115
     * (*) see wcfs/client/wcfs.h and wcfs/wcfs.go
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
116 117
     */

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
118

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
119 120 121
    /* mmap_setup_read is called to setup new read-only mapping of file[blk +blklen).
     *
     * The mapping will be used as the base read-only layer for vma.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
122
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
123 124
     * After setup bigfile backend manages the mapping and can change it dynamically
     * e.g. due to changes to the file from outside. However before changing a page,
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
125
     * the backend must check if that page was already dirtied by virtmem and if
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
126 127 128 129 130
     * so don't change that page until virtmem calls .remmap_blk_read.
     *
     * The checking has to be done with virtmem lock held. A sketch of mapping
     * update sequence is as below:
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
131 132
     *      // backend detects that block is changed from outside
     *      // fileh is vma->fileh - file handle with which the vma is associated
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
133
     *      virt_lock()
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
134 135 136 137
     *      for (pgoff : page_offsets_covered_by(blk))
     *          if (!__fileh_page_isdirty(fileh, pgoff)) {
     *              // update mappings for all fileh's vma that cover pgoff
     *          }
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
138
     *      virt_unlock()
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
139
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
140 141
     * mmap_setup_read can use vma.mmap_overlay_server to associate vma with
     * object pointer specific to serving created mapping.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
142
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
143
     * Called under virtmem lock.       XXX easy to rework to call with !virt_lock
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
144
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
145 146
     * NOTE blk and blklen are in blocks, not pages.
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
147
     * @addr    NULL - mmap at anywhere,    !NULL - mmap exactly at addr.
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
148 149
     * @return  !NULL - mapped there,       NULL - error.
     */
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
150
    void* (*mmap_setup_read) (VMA *vma, BigFile *file, blk_t blk, size_t blklen);
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
151

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
152

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
153 154 155
    /* remmap_blk_read is called to remmap a block into vma again, after e.g.
     * RW dirty page was discarded.
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
156
     * Called under virtmem lock.       XXX hard to rework to call with !virt_lock
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
157 158 159
     *
     * XXX error -> bug (must not fail)
     */
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
160
    int (*remmap_blk_read) (VMA *vma, BigFile *file, blk_t blk);
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
161

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
162 163
    /* munmap is called when vma set up via mmap_setup_read is going to be unmapped.
     *
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
164
     * Called under virtmem lock.       XXX easy to rework to call with !virt_lock
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
165 166
     * Must not fail.
     */
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
167
    void (*munmap) (VMA *vma, BigFile *file);
168
};
Kirill Smelkov's avatar
.  
Kirill Smelkov committed
169
typedef struct bigfile_ops bigfile_ops;
170

Kirill Smelkov's avatar
.  
Kirill Smelkov committed
171 172 173 174
#ifdef __cplusplus
}
#endif

175
#endif