• 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 #ifndef WITH_ANDROID
23 #include <scsi/sg.h>
24 #endif
25 #include <linux/hdreg.h>
26 #include <linux/limits.h>
27 
28 #include <f2fs_fs.h>
29 
30 #ifndef WITH_ANDROID
31 /* SCSI command for standard inquiry*/
32 #define MODELINQUIRY	0x12,0x00,0x00,0x00,0x4A,0x00
33 #endif
34 
35 #ifndef _WIN32 /* O_BINARY is windows-specific flag */
36 #define O_BINARY 0
37 #endif
38 
39 /*
40  * UTF conversion codes are Copied from exfat tools.
41  */
utf8_to_wchar(const char * input,wchar_t * wc,size_t insize)42 static const char *utf8_to_wchar(const char *input, wchar_t *wc,
43 		size_t insize)
44 {
45 	if ((input[0] & 0x80) == 0 && insize >= 1) {
46 		*wc = (wchar_t) input[0];
47 		return input + 1;
48 	}
49 	if ((input[0] & 0xe0) == 0xc0 && insize >= 2) {
50 		*wc = (((wchar_t) input[0] & 0x1f) << 6) |
51 		       ((wchar_t) input[1] & 0x3f);
52 		return input + 2;
53 	}
54 	if ((input[0] & 0xf0) == 0xe0 && insize >= 3) {
55 		*wc = (((wchar_t) input[0] & 0x0f) << 12) |
56 		      (((wchar_t) input[1] & 0x3f) << 6) |
57 		       ((wchar_t) input[2] & 0x3f);
58 		return input + 3;
59 	}
60 	if ((input[0] & 0xf8) == 0xf0 && insize >= 4) {
61 		*wc = (((wchar_t) input[0] & 0x07) << 18) |
62 		      (((wchar_t) input[1] & 0x3f) << 12) |
63 		      (((wchar_t) input[2] & 0x3f) << 6) |
64 		       ((wchar_t) input[3] & 0x3f);
65 		return input + 4;
66 	}
67 	if ((input[0] & 0xfc) == 0xf8 && insize >= 5) {
68 		*wc = (((wchar_t) input[0] & 0x03) << 24) |
69 		      (((wchar_t) input[1] & 0x3f) << 18) |
70 		      (((wchar_t) input[2] & 0x3f) << 12) |
71 		      (((wchar_t) input[3] & 0x3f) << 6) |
72 		       ((wchar_t) input[4] & 0x3f);
73 		return input + 5;
74 	}
75 	if ((input[0] & 0xfe) == 0xfc && insize >= 6) {
76 		*wc = (((wchar_t) input[0] & 0x01) << 30) |
77 		      (((wchar_t) input[1] & 0x3f) << 24) |
78 		      (((wchar_t) input[2] & 0x3f) << 18) |
79 		      (((wchar_t) input[3] & 0x3f) << 12) |
80 		      (((wchar_t) input[4] & 0x3f) << 6) |
81 		       ((wchar_t) input[5] & 0x3f);
82 		return input + 6;
83 	}
84 	return NULL;
85 }
86 
wchar_to_utf16(u_int16_t * output,wchar_t wc,size_t outsize)87 static u_int16_t *wchar_to_utf16(u_int16_t *output, wchar_t wc, size_t outsize)
88 {
89 	if (wc <= 0xffff) {
90 		if (outsize == 0)
91 			return NULL;
92 		output[0] = cpu_to_le16(wc);
93 		return output + 1;
94 	}
95 	if (outsize < 2)
96 		return NULL;
97 	wc -= 0x10000;
98 	output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
99 	output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
100 	return output + 2;
101 }
102 
utf8_to_utf16(u_int16_t * output,const char * input,size_t outsize,size_t insize)103 int utf8_to_utf16(u_int16_t *output, const char *input, size_t outsize,
104 		size_t insize)
105 {
106 	const char *inp = input;
107 	u_int16_t *outp = output;
108 	wchar_t wc;
109 
110 	while ((size_t)(inp - input) < insize && *inp) {
111 		inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
112 		if (inp == NULL) {
113 			DBG(0, "illegal UTF-8 sequence\n");
114 			return -EILSEQ;
115 		}
116 		outp = wchar_to_utf16(outp, wc, outsize - (outp - output));
117 		if (outp == NULL) {
118 			DBG(0, "name is too long\n");
119 			return -ENAMETOOLONG;
120 		}
121 	}
122 	*outp = cpu_to_le16(0);
123 	return 0;
124 }
125 
utf16_to_wchar(const u_int16_t * input,wchar_t * wc,size_t insize)126 static const u_int16_t *utf16_to_wchar(const u_int16_t *input, wchar_t *wc,
127 		size_t insize)
128 {
129 	if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
130 		if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
131 			return NULL;
132 		*wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
133 		*wc |= (le16_to_cpu(input[1]) & 0x3ff);
134 		*wc += 0x10000;
135 		return input + 2;
136 	} else {
137 		*wc = le16_to_cpu(*input);
138 		return input + 1;
139 	}
140 }
141 
wchar_to_utf8(char * output,wchar_t wc,size_t outsize)142 static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
143 {
144 	if (wc <= 0x7f) {
145 		if (outsize < 1)
146 			return NULL;
147 		*output++ = (char) wc;
148 	} else if (wc <= 0x7ff) {
149 		if (outsize < 2)
150 			return NULL;
151 		*output++ = 0xc0 | (wc >> 6);
152 		*output++ = 0x80 | (wc & 0x3f);
153 	} else if (wc <= 0xffff) {
154 		if (outsize < 3)
155 			return NULL;
156 		*output++ = 0xe0 | (wc >> 12);
157 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
158 		*output++ = 0x80 | (wc & 0x3f);
159 	} else if (wc <= 0x1fffff) {
160 		if (outsize < 4)
161 			return NULL;
162 		*output++ = 0xf0 | (wc >> 18);
163 		*output++ = 0x80 | ((wc >> 12) & 0x3f);
164 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
165 		*output++ = 0x80 | (wc & 0x3f);
166 	} else if (wc <= 0x3ffffff) {
167 		if (outsize < 5)
168 			return NULL;
169 		*output++ = 0xf8 | (wc >> 24);
170 		*output++ = 0x80 | ((wc >> 18) & 0x3f);
171 		*output++ = 0x80 | ((wc >> 12) & 0x3f);
172 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
173 		*output++ = 0x80 | (wc & 0x3f);
174 	} else if (wc <= 0x7fffffff) {
175 		if (outsize < 6)
176 			return NULL;
177 		*output++ = 0xfc | (wc >> 30);
178 		*output++ = 0x80 | ((wc >> 24) & 0x3f);
179 		*output++ = 0x80 | ((wc >> 18) & 0x3f);
180 		*output++ = 0x80 | ((wc >> 12) & 0x3f);
181 		*output++ = 0x80 | ((wc >> 6) & 0x3f);
182 		*output++ = 0x80 | (wc & 0x3f);
183 	} else
184 		return NULL;
185 
186 	return output;
187 }
188 
utf16_to_utf8(char * output,const u_int16_t * input,size_t outsize,size_t insize)189 int utf16_to_utf8(char *output, const u_int16_t *input, size_t outsize,
190 		size_t insize)
191 {
192 	const u_int16_t *inp = input;
193 	char *outp = output;
194 	wchar_t wc;
195 
196 	while ((size_t)(inp - input) < insize && le16_to_cpu(*inp)) {
197 		inp = utf16_to_wchar(inp, &wc, insize - (inp - input));
198 		if (inp == NULL) {
199 			DBG(0, "illegal UTF-16 sequence\n");
200 			return -EILSEQ;
201 		}
202 		outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
203 		if (outp == NULL) {
204 			DBG(0, "name is too long\n");
205 			return -ENAMETOOLONG;
206 		}
207 	}
208 	*outp = '\0';
209 	return 0;
210 }
211 
log_base_2(u_int32_t num)212 int log_base_2(u_int32_t num)
213 {
214 	int ret = 0;
215 	if (num <= 0 || (num & (num - 1)) != 0)
216 		return -1;
217 
218 	while (num >>= 1)
219 		ret++;
220 	return ret;
221 }
222 
223 /*
224  * f2fs bit operations
225  */
226 static const int bits_in_byte[256] = {
227 	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
228 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
229 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
230 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
231 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
232 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
233 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
234 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
235 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
236 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
237 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
238 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
239 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
240 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
241 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
242 	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
243 };
244 
get_bits_in_byte(unsigned char n)245 int get_bits_in_byte(unsigned char n)
246 {
247 	return bits_in_byte[n];
248 }
249 
test_and_set_bit_le(u32 nr,u8 * addr)250 int test_and_set_bit_le(u32 nr, u8 *addr)
251 {
252 	int mask, retval;
253 
254 	addr += nr >> 3;
255 	mask = 1 << ((nr & 0x07));
256 	retval = mask & *addr;
257 	*addr |= mask;
258 	return retval;
259 }
260 
test_and_clear_bit_le(u32 nr,u8 * addr)261 int test_and_clear_bit_le(u32 nr, u8 *addr)
262 {
263 	int mask, retval;
264 
265 	addr += nr >> 3;
266 	mask = 1 << ((nr & 0x07));
267 	retval = mask & *addr;
268 	*addr &= ~mask;
269 	return retval;
270 }
271 
test_bit_le(u32 nr,const u8 * addr)272 int test_bit_le(u32 nr, const u8 *addr)
273 {
274 	return ((1 << (nr & 7)) & (addr[nr >> 3]));
275 }
276 
f2fs_test_bit(unsigned int nr,const char * p)277 int f2fs_test_bit(unsigned int nr, const char *p)
278 {
279 	int mask;
280 	char *addr = (char *)p;
281 
282 	addr += (nr >> 3);
283 	mask = 1 << (7 - (nr & 0x07));
284 	return (mask & *addr) != 0;
285 }
286 
f2fs_set_bit(unsigned int nr,char * addr)287 int f2fs_set_bit(unsigned int nr, char *addr)
288 {
289 	int mask;
290 	int ret;
291 
292 	addr += (nr >> 3);
293 	mask = 1 << (7 - (nr & 0x07));
294 	ret = mask & *addr;
295 	*addr |= mask;
296 	return ret;
297 }
298 
f2fs_clear_bit(unsigned int nr,char * addr)299 int f2fs_clear_bit(unsigned int nr, char *addr)
300 {
301 	int mask;
302 	int ret;
303 
304 	addr += (nr >> 3);
305 	mask = 1 << (7 - (nr & 0x07));
306 	ret = mask & *addr;
307 	*addr &= ~mask;
308 	return ret;
309 }
310 
__ffs(u8 word)311 static inline u64 __ffs(u8 word)
312 {
313 	int num = 0;
314 
315 	if ((word & 0xf) == 0) {
316 		num += 4;
317 		word >>= 4;
318 	}
319 	if ((word & 0x3) == 0) {
320 		num += 2;
321 		word >>= 2;
322 	}
323 	if ((word & 0x1) == 0)
324 		num += 1;
325 	return num;
326 }
327 
328 /* Copied from linux/lib/find_bit.c */
329 #define BITMAP_FIRST_BYTE_MASK(start) (0xff << ((start) & (BITS_PER_BYTE - 1)))
330 
_find_next_bit_le(const u8 * addr,u64 nbits,u64 start,char invert)331 static u64 _find_next_bit_le(const u8 *addr, u64 nbits, u64 start, char invert)
332 {
333 	u8 tmp;
334 
335 	if (!nbits || start >= nbits)
336 		return nbits;
337 
338 	tmp = addr[start / BITS_PER_BYTE] ^ invert;
339 
340 	/* Handle 1st word. */
341 	tmp &= BITMAP_FIRST_BYTE_MASK(start);
342 	start = round_down(start, BITS_PER_BYTE);
343 
344 	while (!tmp) {
345 		start += BITS_PER_BYTE;
346 		if (start >= nbits)
347 			return nbits;
348 
349 		tmp = addr[start / BITS_PER_BYTE] ^ invert;
350 	}
351 
352 	return min(start + __ffs(tmp), nbits);
353 }
354 
find_next_bit_le(const u8 * addr,u64 size,u64 offset)355 u64 find_next_bit_le(const u8 *addr, u64 size, u64 offset)
356 {
357 	return _find_next_bit_le(addr, size, offset, 0);
358 }
359 
360 
find_next_zero_bit_le(const u8 * addr,u64 size,u64 offset)361 u64 find_next_zero_bit_le(const u8 *addr, u64 size, u64 offset)
362 {
363 	return _find_next_bit_le(addr, size, offset, 0xff);
364 }
365 
366 /*
367  * Hashing code adapted from ext3
368  */
369 #define DELTA 0x9E3779B9
370 
TEA_transform(unsigned int buf[4],unsigned int const in[])371 static void TEA_transform(unsigned int buf[4], unsigned int const in[])
372 {
373 	__u32 sum = 0;
374 	__u32 b0 = buf[0], b1 = buf[1];
375 	__u32 a = in[0], b = in[1], c = in[2], d = in[3];
376 	int     n = 16;
377 
378 	do {
379 		sum += DELTA;
380 		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
381 		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
382 	} while (--n);
383 
384 	buf[0] += b0;
385 	buf[1] += b1;
386 
387 }
388 
str2hashbuf(const unsigned char * msg,int len,unsigned int * buf,int num)389 static void str2hashbuf(const unsigned char *msg, int len,
390 					unsigned int *buf, int num)
391 {
392 	unsigned pad, val;
393 	int i;
394 
395 	pad = (__u32)len | ((__u32)len << 8);
396 	pad |= pad << 16;
397 
398 	val = pad;
399 	if (len > num * 4)
400 		len = num * 4;
401 	for (i = 0; i < len; i++) {
402 		if ((i % 4) == 0)
403 			val = pad;
404 		val = msg[i] + (val << 8);
405 		if ((i % 4) == 3) {
406 			*buf++ = val;
407 			val = pad;
408 			num--;
409 		}
410 	}
411 	if (--num >= 0)
412 		*buf++ = val;
413 	while (--num >= 0)
414 		*buf++ = pad;
415 
416 }
417 
418 /**
419  * Return hash value of directory entry
420  * @param name          dentry name
421  * @param len           name lenth
422  * @return              return on success hash value, errno on failure
423  */
f2fs_dentry_hash(const unsigned char * name,int len)424 f2fs_hash_t f2fs_dentry_hash(const unsigned char *name, int len)
425 {
426 	__u32 hash;
427 	f2fs_hash_t	f2fs_hash;
428 	const unsigned char	*p;
429 	__u32 in[8], buf[4];
430 
431 	/* special hash codes for special dentries */
432 	if ((len <= 2) && (name[0] == '.') &&
433 		(name[1] == '.' || name[1] == '\0'))
434 		return 0;
435 
436 	/* Initialize the default seed for the hash checksum functions */
437 	buf[0] = 0x67452301;
438 	buf[1] = 0xefcdab89;
439 	buf[2] = 0x98badcfe;
440 	buf[3] = 0x10325476;
441 
442 	p = name;
443 	while (1) {
444 		str2hashbuf(p, len, in, 4);
445 		TEA_transform(buf, in);
446 		p += 16;
447 		if (len <= 16)
448 			break;
449 		len -= 16;
450 	}
451 	hash = buf[0];
452 
453 	f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT);
454 	return f2fs_hash;
455 }
456 
addrs_per_inode(struct f2fs_inode * i)457 unsigned int addrs_per_inode(struct f2fs_inode *i)
458 {
459 	if (i->i_inline & F2FS_INLINE_XATTR)
460 		return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS;
461 	return DEF_ADDRS_PER_INODE;
462 }
463 
464 /*
465  * CRC32
466  */
467 #define CRCPOLY_LE 0xedb88320
468 
f2fs_cal_crc32(u_int32_t crc,void * buf,int len)469 u_int32_t f2fs_cal_crc32(u_int32_t crc, void *buf, int len)
470 {
471 	int i;
472 	unsigned char *p = (unsigned char *)buf;
473 	while (len--) {
474 		crc ^= *p++;
475 		for (i = 0; i < 8; i++)
476 			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
477 	}
478 	return crc;
479 }
480 
f2fs_crc_valid(u_int32_t blk_crc,void * buf,int len)481 int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
482 {
483 	u_int32_t cal_crc = 0;
484 
485 	cal_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, buf, len);
486 
487 	if (cal_crc != blk_crc)	{
488 		DBG(0,"CRC validation failed: cal_crc = %u, "
489 			"blk_crc = %u buff_size = 0x%x\n",
490 			cal_crc, blk_crc, len);
491 		return -1;
492 	}
493 	return 0;
494 }
495 
496 /*
497  * try to identify the root device
498  */
get_rootdev()499 const char *get_rootdev()
500 {
501 	struct stat sb;
502 	int fd, ret;
503 	char buf[32];
504 	char *uevent, *ptr;
505 
506 	static char rootdev[PATH_MAX + 1];
507 
508 	if (stat("/", &sb) == -1)
509 		return NULL;
510 
511 	snprintf(buf, 32, "/sys/dev/block/%u:%u/uevent",
512 		major(sb.st_dev), minor(sb.st_dev));
513 
514 	fd = open(buf, O_RDONLY);
515 
516 	if (fd < 0)
517 		return NULL;
518 
519 	ret = lseek(fd, (off_t)0, SEEK_END);
520 	(void)lseek(fd, (off_t)0, SEEK_SET);
521 
522 	if (ret == -1) {
523 		close(fd);
524 		return NULL;
525 	}
526 
527 	uevent = malloc(ret + 1);
528 	uevent[ret] = '\0';
529 
530 	ret = read(fd, uevent, ret);
531 	close(fd);
532 
533 	ptr = strstr(uevent, "DEVNAME");
534 	if (!ptr)
535 		return NULL;
536 
537 	ret = sscanf(ptr, "DEVNAME=%s\n", buf);
538 	snprintf(rootdev, PATH_MAX + 1, "/dev/%s", buf);
539 
540 	return rootdev;
541 }
542 
543 /*
544  * device information
545  */
f2fs_init_configuration(void)546 void f2fs_init_configuration(void)
547 {
548 	int i;
549 
550 	c.ndevs = 1;
551 	c.total_sectors = 0;
552 	c.sector_size = 0;
553 	c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
554 	c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
555 	c.rootdev_name = get_rootdev();
556 	c.wanted_total_sectors = -1;
557 	c.zoned_mode = 0;
558 	c.zoned_model = 0;
559 	c.zone_blocks = 0;
560 
561 	for (i = 0; i < MAX_DEVICES; i++) {
562 		memset(&c.devices[i], 0, sizeof(struct device_info));
563 		c.devices[i].fd = -1;
564 		c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
565 		c.devices[i].end_blkaddr = -1;
566 		c.devices[i].zoned_model = F2FS_ZONED_NONE;
567 	}
568 
569 	/* calculated by overprovision ratio */
570 	c.reserved_segments = 0;
571 	c.overprovision = 0;
572 	c.segs_per_sec = 1;
573 	c.secs_per_zone = 1;
574 	c.segs_per_zone = 1;
575 	c.heap = 0;
576 	c.vol_label = "";
577 	c.trim = 1;
578 	c.trimmed = 0;
579 	c.ro = 0;
580 	c.kd = -1;
581 }
582 
is_mounted(const char * mpt,const char * device)583 static int is_mounted(const char *mpt, const char *device)
584 {
585 	FILE *file = NULL;
586 	struct mntent *mnt = NULL;
587 
588 	file = setmntent(mpt, "r");
589 	if (file == NULL)
590 		return 0;
591 
592 	while ((mnt = getmntent(file)) != NULL) {
593 		if (!strcmp(device, mnt->mnt_fsname)) {
594 #ifdef MNTOPT_RO
595 			if (hasmntopt(mnt, MNTOPT_RO))
596 				c.ro = 1;
597 #endif
598 			break;
599 		}
600 	}
601 	endmntent(file);
602 	return mnt ? 1 : 0;
603 }
604 
f2fs_dev_is_umounted(char * path)605 int f2fs_dev_is_umounted(char *path)
606 {
607 	struct stat st_buf;
608 	int is_rootdev = 0;
609 	int ret = 0;
610 
611 	if (c.rootdev_name && !strcmp(path, c.rootdev_name))
612 		is_rootdev = 1;
613 
614 	/*
615 	 * try with /proc/mounts fist to detect RDONLY.
616 	 * f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
617 	 */
618 	ret = is_mounted("/proc/mounts", path);
619 	if (ret) {
620 		MSG(0, "Info: Mounted device!\n");
621 		return -1;
622 	}
623 
624 	ret = is_mounted(MOUNTED, path);
625 	if (ret) {
626 		MSG(0, "Info: Mounted device!\n");
627 		return -1;
628 	}
629 
630 	/*
631 	 * If we are supposed to operate on the root device, then
632 	 * also check the mounts for '/dev/root', which sometimes
633 	 * functions as an alias for the root device.
634 	 */
635 	if (is_rootdev) {
636 		ret = is_mounted("/proc/mounts", "/dev/root");
637 		if (ret) {
638 			MSG(0, "Info: Mounted device!\n");
639 			return -1;
640 		}
641 	}
642 
643 	/*
644 	 * If f2fs is umounted with -l, the process can still use
645 	 * the file system. In this case, we should not format.
646 	 */
647 	if (stat(path, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
648 		int fd = open(path, O_RDONLY | O_EXCL);
649 
650 		if (fd >= 0) {
651 			close(fd);
652 		} else if (errno == EBUSY) {
653 			MSG(0, "\tError: In use by the system!\n");
654 			return -1;
655 		}
656 	}
657 	return 0;
658 }
659 
f2fs_devs_are_umounted(void)660 int f2fs_devs_are_umounted(void)
661 {
662 	int i;
663 
664 	for (i = 0; i < c.ndevs; i++)
665 		if (f2fs_dev_is_umounted((char *)c.devices[i].path))
666 			return -1;
667 	return 0;
668 }
669 
get_kernel_version(__u8 * version)670 void get_kernel_version(__u8 *version)
671 {
672 	int i;
673 	for (i = 0; i < VERSION_LEN; i++) {
674 		if (version[i] == '\n')
675 			break;
676 	}
677 	memset(version + i, 0, VERSION_LEN + 1 - i);
678 }
679 
get_device_info(int i)680 int get_device_info(int i)
681 {
682 	int32_t fd = 0;
683 	uint32_t sector_size;
684 #ifndef BLKGETSIZE64
685 	uint32_t total_sectors;
686 #endif
687 	struct stat stat_buf;
688 	struct hd_geometry geom;
689 #ifndef WITH_ANDROID
690 	sg_io_hdr_t io_hdr;
691 	unsigned char reply_buffer[96] = {0};
692 	unsigned char model_inq[6] = {MODELINQUIRY};
693 #endif
694 	struct device_info *dev = c.devices + i;
695 
696 	if (c.sparse_mode) {
697 		fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
698 	} else {
699 		fd = open((char *)dev->path, O_RDWR);
700 	}
701 	if (fd < 0) {
702 		MSG(0, "\tError: Failed to open the device!\n");
703 		return -1;
704 	}
705 
706 	dev->fd = fd;
707 
708 	if (c.kd == -1) {
709 		c.kd = open("/proc/version", O_RDONLY);
710 		if (c.kd < 0) {
711 			MSG(0, "\tInfo: No support kernel version!\n");
712 			c.kd = -2;
713 		}
714 	}
715 
716 	if (fstat(fd, &stat_buf) < 0 ) {
717 		MSG(0, "\tError: Failed to get the device stat!\n");
718 		return -1;
719 	}
720 
721 	if (c.sparse_mode) {
722 		dev->total_sectors = c.device_size / dev->sector_size;
723 	} else if (S_ISREG(stat_buf.st_mode)) {
724 		dev->total_sectors = stat_buf.st_size / dev->sector_size;
725 	} else if (S_ISBLK(stat_buf.st_mode)) {
726 		if (ioctl(fd, BLKSSZGET, &sector_size) < 0)
727 			MSG(0, "\tError: Using the default sector size\n");
728 		else if (dev->sector_size < sector_size)
729 			dev->sector_size = sector_size;
730 #ifdef BLKGETSIZE64
731 		if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
732 			MSG(0, "\tError: Cannot get the device size\n");
733 			return -1;
734 		}
735 #else
736 		if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
737 			MSG(0, "\tError: Cannot get the device size\n");
738 			return -1;
739 		}
740 		dev->total_sectors = total_sectors;
741 #endif
742 		dev->total_sectors /= dev->sector_size;
743 
744 		if (i == 0) {
745 			if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
746 				c.start_sector = 0;
747 			else
748 				c.start_sector = geom.start;
749 		}
750 
751 #ifndef WITH_ANDROID
752 		/* Send INQUIRY command */
753 		memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
754 		io_hdr.interface_id = 'S';
755 		io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
756 		io_hdr.dxfer_len = sizeof(reply_buffer);
757 		io_hdr.dxferp = reply_buffer;
758 		io_hdr.cmd_len = sizeof(model_inq);
759 		io_hdr.cmdp = model_inq;
760 		io_hdr.timeout = 1000;
761 
762 		if (!ioctl(fd, SG_IO, &io_hdr)) {
763 			int i = 16;
764 
765 			MSG(0, "Info: [%s] Disk Model: ",
766 					dev->path);
767 			while (reply_buffer[i] != '`' && i < 80)
768 				printf("%c", reply_buffer[i++]);
769 			printf("\n");
770 		}
771 #endif
772 	} else {
773 		MSG(0, "\tError: Volume type is not supported!!!\n");
774 		return -1;
775 	}
776 
777 	if (!c.sector_size) {
778 		c.sector_size = dev->sector_size;
779 		c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
780 	} else if (c.sector_size != c.devices[i].sector_size) {
781 		MSG(0, "\tError: Different sector sizes!!!\n");
782 		return -1;
783 	}
784 
785 #ifndef WITH_ANDROID
786 	if (S_ISBLK(stat_buf.st_mode))
787 		f2fs_get_zoned_model(i);
788 
789 	if (dev->zoned_model != F2FS_ZONED_NONE) {
790 		if (dev->zoned_model == F2FS_ZONED_HM)
791 			c.zoned_model = F2FS_ZONED_HM;
792 
793 		if (f2fs_get_zone_blocks(i)) {
794 			MSG(0, "\tError: Failed to get number of blocks per zone\n");
795 			return -1;
796 		}
797 
798 		if (f2fs_check_zones(i)) {
799 			MSG(0, "\tError: Failed to check zone configuration\n");
800 			return -1;
801 		}
802 		MSG(0, "Info: Host-%s zoned block device:\n",
803 				(dev->zoned_model == F2FS_ZONED_HA) ?
804 					"aware" : "managed");
805 		MSG(0, "      %u zones, %u randomly writeable zones\n",
806 				dev->nr_zones, dev->nr_rnd_zones);
807 		MSG(0, "      %lu blocks per zone\n",
808 				dev->zone_blocks);
809 	}
810 #endif
811 	c.total_sectors += dev->total_sectors;
812 	return 0;
813 }
814 
f2fs_get_device_info(void)815 int f2fs_get_device_info(void)
816 {
817 	int i;
818 
819 	for (i = 0; i < c.ndevs; i++)
820 		if (get_device_info(i))
821 			return -1;
822 
823 	if (c.wanted_total_sectors < c.total_sectors) {
824 		MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
825 				c.total_sectors, c.sector_size);
826 		c.total_sectors = c.wanted_total_sectors;
827 		c.devices[0].total_sectors = c.total_sectors;
828 	}
829 	if (c.total_sectors * c.sector_size >
830 		(u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
831 		MSG(0, "\tError: F2FS can support 16TB at most!!!\n");
832 		return -1;
833 	}
834 
835 	for (i = 0; i < c.ndevs; i++) {
836 		if (c.devices[i].zoned_model != F2FS_ZONED_NONE) {
837 			if (c.zone_blocks &&
838 				c.zone_blocks != c.devices[i].zone_blocks) {
839 				MSG(0, "\tError: not support different zone sizes!!!\n");
840 				return -1;
841 			}
842 			c.zone_blocks = c.devices[i].zone_blocks;
843 		}
844 	}
845 
846 	/*
847 	 * Align sections to the device zone size
848 	 * and align F2FS zones to the device zones.
849 	 */
850 	if (c.zone_blocks) {
851 		c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
852 		c.secs_per_zone = 1;
853 	} else {
854 		c.zoned_mode = 0;
855 	}
856 
857 	c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
858 
859 	MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
860 	MSG(0, "Info: Sections per zone = %d\n", c.secs_per_zone);
861 	MSG(0, "Info: sector size = %u\n", c.sector_size);
862 	MSG(0, "Info: total sectors = %"PRIu64" (%"PRIu64" MB)\n",
863 				c.total_sectors, (c.total_sectors *
864 					(c.sector_size >> 9)) >> 11);
865 	return 0;
866 }
867