]>
Commit | Line | Data |
---|---|---|
81eedcae TL |
1 | ====== |
2 | LazyIO | |
3 | ====== | |
4 | ||
5 | LazyIO relaxes POSIX semantics. Buffered reads/writes are allowed even when a | |
6 | file is opened by multiple applications on multiple clients. Applications are | |
7 | responsible for managing cache coherency themselves. | |
8 | ||
9 | Libcephfs supports LazyIO since nautilus release. | |
10 | ||
11 | Enable LazyIO | |
12 | ============= | |
13 | ||
14 | LazyIO can be enabled by following ways. | |
15 | ||
16 | - ``client_force_lazyio`` option enables LAZY_IO globally for libcephfs and | |
17 | ceph-fuse mount. | |
18 | ||
19 | - ``ceph_lazyio(...)`` and ``ceph_ll_lazyio(...)`` enable LAZY_IO for file handle | |
20 | in libcephfs. | |
21 | ||
9f95a23c TL |
22 | Using LazyIO |
23 | ============ | |
24 | ||
25 | LazyIO includes two methods ``lazyio_propagate()`` and ``lazyio_synchronize()``. | |
26 | With LazyIO enabled, writes may not be visble to other clients until | |
27 | ``lazyio_propagate()`` is called. Reads may come from local cache (irrespective of | |
28 | changes to the file by other clients) until ``lazyio_synchronize()`` is called. | |
29 | ||
30 | - ``lazyio_propagate(int fd, loff_t offset, size_t count)`` - Ensures that any | |
31 | buffered writes of the client, in the specific region (offset to offset+count), | |
32 | has been propagated to the shared file. If offset and count are both 0, the | |
33 | operation is performed on the entire file. Currently only this is supported. | |
34 | ||
35 | - ``lazyio_synchronize(int fd, loff_t offset, size_t count)`` - Ensures that the | |
36 | client is, in a subsequent read call, able to read the updated file with all | |
37 | the propagated writes of the other clients. In CephFS this is facilitated by | |
38 | invalidating the file caches pertaining to the inode and hence forces the | |
39 | client to refetch/recache the data from the updated file. Also if the write cache | |
40 | of the calling client is dirty (not propagated), lazyio_synchronize() flushes it as well. | |
41 | ||
42 | An example usage (utilizing libcephfs) is given below. This is a sample I/O loop for a | |
43 | particular client/file descriptor in a parallel application: | |
44 | ||
45 | :: | |
46 | ||
47 | /* Client a (ca) opens the shared file file.txt */ | |
48 | int fda = ceph_open(ca, "shared_file.txt", O_CREAT|O_RDWR, 0644); | |
49 | ||
50 | /* Enable LazyIO for fda */ | |
51 | ceph_lazyio(ca, fda, 1)); | |
52 | ||
53 | for(i = 0; i < num_iters; i++) { | |
54 | char out_buf[] = "fooooooooo"; | |
55 | ||
56 | ceph_write(ca, fda, out_buf, sizeof(out_buf), i); | |
57 | /* Propagate the writes associated with fda to the backing storage*/ | |
58 | ceph_propagate(ca, fda, 0, 0); | |
59 | ||
60 | /* The barrier makes sure changes associated with all file descriptors | |
61 | are propagated so that there is certainty that the backing file | |
62 | is upto date */ | |
63 | application_specific_barrier(); | |
64 | ||
65 | char in_buf[40]; | |
66 | /* Calling ceph_lazyio_synchronize here will ascertain that ca will | |
67 | read the updated file with the propagated changes and not read | |
68 | stale cached data */ | |
69 | ceph_lazyio_synchronize(ca, fda, 0, 0); | |
70 | ceph_read(ca, fda, in_buf, sizeof(in_buf), 0); | |
71 | ||
72 | /* A barrier is required here before returning to the next write | |
73 | phase so as to avoid overwriting the portion of the shared file still | |
74 | being read by another file descriptor */ | |
75 | application_specific_barrier(); | |
76 | } |