• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * libf2fs.c
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *             http://www.samsung.com/
6  *
7  * Dual licensed under the GPL or LGPL version 2 licenses.
8  */
9 #define _LARGEFILE64_SOURCE
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <mntent.h>
18 #include <time.h>
19 #include <sys/stat.h>
20 #include <sys/mount.h>
21 #include <sys/ioctl.h>
22 #include <linux/hdreg.h>
23 
24 #include <f2fs_fs.h>
25 
26 struct f2fs_configuration c;
27 
28 #ifdef WITH_ANDROID
29 #include <sparse/sparse.h>
30 struct sparse_file *f2fs_sparse_file;
31 
32 struct buf_item {
33 	void *buf;
34 	size_t len;
35 	struct buf_item *next;
36 };
37 
38 struct buf_item *buf_list;
39 #endif
40 
__get_device_fd(__u64 * offset)41 static int __get_device_fd(__u64 *offset)
42 {
43 	__u64 blk_addr = *offset >> F2FS_BLKSIZE_BITS;
44 	int i;
45 
46 	for (i = 0; i < c.ndevs; i++) {
47 		if (c.devices[i].start_blkaddr <= blk_addr &&
48 				c.devices[i].end_blkaddr >= blk_addr) {
49 			*offset -=
50 				c.devices[i].start_blkaddr << F2FS_BLKSIZE_BITS;
51 			return c.devices[i].fd;
52 		}
53 	}
54 	return -1;
55 }
56 
57 /*
58  * IO interfaces
59  */
dev_read_version(void * buf,__u64 offset,size_t len)60 int dev_read_version(void *buf, __u64 offset, size_t len)
61 {
62 	if (c.sparse_mode)
63 		return 0;
64 	if (lseek64(c.kd, (off64_t)offset, SEEK_SET) < 0)
65 		return -1;
66 	if (read(c.kd, buf, len) < 0)
67 		return -1;
68 	return 0;
69 }
70 
dev_read(void * buf,__u64 offset,size_t len)71 int dev_read(void *buf, __u64 offset, size_t len)
72 {
73 	int fd;
74 
75 	if (c.sparse_mode)
76 		return 0;
77 
78 	fd = __get_device_fd(&offset);
79 	if (fd < 0)
80 		return fd;
81 
82 	if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
83 		return -1;
84 	if (read(fd, buf, len) < 0)
85 		return -1;
86 	return 0;
87 }
88 
dev_readahead(__u64 offset,size_t len)89 int dev_readahead(__u64 offset, size_t len)
90 {
91 	int fd = __get_device_fd(&offset);
92 
93 	if (fd < 0)
94 		return fd;
95 #ifdef POSIX_FADV_WILLNEED
96 	return posix_fadvise(fd, offset, len, POSIX_FADV_WILLNEED);
97 #else
98 	return 0;
99 #endif
100 }
101 
102 #ifdef WITH_ANDROID
dev_write_sparse(void * buf,__u64 byte_offset,size_t byte_len)103 static int dev_write_sparse(void *buf, __u64 byte_offset, size_t byte_len)
104 {
105 	struct buf_item *bi = calloc(1, sizeof(struct buf_item));
106 
107 	if (bi == NULL) {
108 		return -1;
109 	}
110 	bi->buf = malloc(byte_len);
111 	if (bi->buf == NULL) {
112 		free(bi);
113 		return -1;
114 	}
115 
116 	bi->len = byte_len;
117 	memcpy(bi->buf, buf, byte_len);
118 	bi->next = buf_list;
119 	buf_list = bi;
120 
121 	sparse_file_add_data(f2fs_sparse_file, bi->buf, byte_len, byte_offset/F2FS_BLKSIZE);
122 	return 0;
123 }
124 #else
dev_write_sparse(void * buf,__u64 byte_offset,size_t byte_len)125 static int dev_write_sparse(void *buf, __u64 byte_offset, size_t byte_len) { return 0; }
126 #endif
127 
dev_write(void * buf,__u64 offset,size_t len)128 int dev_write(void *buf, __u64 offset, size_t len)
129 {
130 	int fd;
131 
132 	if (c.sparse_mode)
133 		return dev_write_sparse(buf, offset, len);
134 
135 	fd = __get_device_fd(&offset);
136 	if (fd < 0)
137 		return fd;
138 
139 	if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
140 		return -1;
141 	if (write(fd, buf, len) < 0)
142 		return -1;
143 	return 0;
144 }
145 
dev_write_block(void * buf,__u64 blk_addr)146 int dev_write_block(void *buf, __u64 blk_addr)
147 {
148 	return dev_write(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
149 }
150 
dev_write_dump(void * buf,__u64 offset,size_t len)151 int dev_write_dump(void *buf, __u64 offset, size_t len)
152 {
153 	if (lseek64(c.dump_fd, (off64_t)offset, SEEK_SET) < 0)
154 		return -1;
155 	if (write(c.dump_fd, buf, len) < 0)
156 		return -1;
157 	return 0;
158 }
159 
dev_fill(void * buf,__u64 offset,size_t len)160 int dev_fill(void *buf, __u64 offset, size_t len)
161 {
162 	int fd;
163 
164 	if (c.sparse_mode)
165 		return 0;
166 
167 	fd = __get_device_fd(&offset);
168 	if (fd < 0)
169 		return fd;
170 
171 	/* Only allow fill to zero */
172 	if (*((__u8*)buf))
173 		return -1;
174 	if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
175 		return -1;
176 	if (write(fd, buf, len) < 0)
177 		return -1;
178 	return 0;
179 }
180 
dev_fill_block(void * buf,__u64 blk_addr)181 int dev_fill_block(void *buf, __u64 blk_addr)
182 {
183 	return dev_fill(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
184 }
185 
dev_read_block(void * buf,__u64 blk_addr)186 int dev_read_block(void *buf, __u64 blk_addr)
187 {
188 	return dev_read(buf, blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
189 }
190 
dev_reada_block(__u64 blk_addr)191 int dev_reada_block(__u64 blk_addr)
192 {
193 	return dev_readahead(blk_addr << F2FS_BLKSIZE_BITS, F2FS_BLKSIZE);
194 }
195 
f2fs_finalize_device(void)196 void f2fs_finalize_device(void)
197 {
198 	int i;
199 
200 #ifdef WITH_ANDROID
201 	if (c.sparse_mode) {
202 		sparse_file_write(f2fs_sparse_file, c.devices[0].fd, /*gzip*/0, /*sparse*/1, /*crc*/0);
203 		sparse_file_destroy(f2fs_sparse_file);
204 		while (buf_list) {
205 			struct buf_item *bi = buf_list;
206 			buf_list = buf_list->next;
207 			free(bi->buf);
208 			free(bi);
209 		}
210 		f2fs_sparse_file = NULL;
211 	}
212 #endif
213 
214 	/*
215 	 * We should call fsync() to flush out all the dirty pages
216 	 * in the block device page cache.
217 	 */
218 	for (i = 0; i < c.ndevs; i++) {
219 		if (fsync(c.devices[i].fd) < 0)
220 			MSG(0, "\tError: Could not conduct fsync!!!\n");
221 
222 		if (close(c.devices[i].fd) < 0)
223 			MSG(0, "\tError: Failed to close device file!!!\n");
224 	}
225 	close(c.kd);
226 }
227