2 * nilfs2.c - New Implementation of Log filesystem
4 * Written by Jiro SEKIBA <jir@unicus.jp>
6 * Copyright (C) 2003,2004,2005,2007,2008,2010 Free Software Foundation, Inc.
8 * GRUB is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * GRUB is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
23 /* Filetype information as used in inodes. */
24 #define FILETYPE_INO_MASK 0170000
25 #define FILETYPE_INO_REG 0100000
26 #define FILETYPE_INO_DIRECTORY 0040000
27 #define FILETYPE_INO_SYMLINK 0120000
30 #include <grub/file.h>
32 #include <grub/misc.h>
33 #include <grub/disk.h>
35 #include <grub/types.h>
36 #include <grub/fshelp.h>
38 GRUB_MOD_LICENSE ("GPLv3+");
40 #define NILFS_INODE_BMAP_SIZE 7
42 #define NILFS_SUPORT_REV 2
44 /* Magic value used to identify an nilfs2 filesystem. */
45 #define NILFS2_SUPER_MAGIC 0x3434
46 /* nilfs btree node flag. */
47 #define NILFS_BTREE_NODE_ROOT 0x01
49 /* nilfs btree node level. */
50 #define NILFS_BTREE_LEVEL_DATA 0
51 #define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1)
53 /* nilfs 1st super block posission from beginning of the partition
55 #define NILFS_1ST_SUPER_BLOCK 2
56 /* nilfs 2nd super block posission from beginning of the partition
58 #define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3)
60 #define LOG_INODE_SIZE 7
61 struct grub_nilfs2_inode
63 grub_uint64_t i_blocks
;
65 grub_uint64_t i_ctime
;
66 grub_uint64_t i_mtime
;
67 grub_uint32_t i_ctime_nsec
;
68 grub_uint32_t i_mtime_nsec
;
72 grub_uint16_t i_links_count
;
73 grub_uint32_t i_flags
;
74 grub_uint64_t i_bmap
[NILFS_INODE_BMAP_SIZE
];
75 #define i_device_code i_bmap[0]
76 grub_uint64_t i_xattr
;
77 grub_uint32_t i_generation
;
81 struct grub_nilfs2_super_root
84 grub_uint16_t sr_bytes
;
85 grub_uint16_t sr_flags
;
86 grub_uint64_t sr_nongc_ctime
;
87 struct grub_nilfs2_inode sr_dat
;
88 struct grub_nilfs2_inode sr_cpfile
;
89 struct grub_nilfs2_inode sr_sufile
;
92 struct grub_nilfs2_super_block
94 grub_uint32_t s_rev_level
;
95 grub_uint16_t s_minor_rev_level
;
96 grub_uint16_t s_magic
;
97 grub_uint16_t s_bytes
;
98 grub_uint16_t s_flags
;
99 grub_uint32_t s_crc_seed
;
101 grub_uint32_t s_log_block_size
;
102 grub_uint64_t s_nsegments
;
103 grub_uint64_t s_dev_size
;
104 grub_uint64_t s_first_data_block
;
105 grub_uint32_t s_blocks_per_segment
;
106 grub_uint32_t s_r_segments_percentage
;
107 grub_uint64_t s_last_cno
;
108 grub_uint64_t s_last_pseg
;
109 grub_uint64_t s_last_seq
;
110 grub_uint64_t s_free_blocks_count
;
111 grub_uint64_t s_ctime
;
112 grub_uint64_t s_mtime
;
113 grub_uint64_t s_wtime
;
114 grub_uint16_t s_mnt_count
;
115 grub_uint16_t s_max_mnt_count
;
116 grub_uint16_t s_state
;
117 grub_uint16_t s_errors
;
118 grub_uint64_t s_lastcheck
;
119 grub_uint32_t s_checkinterval
;
120 grub_uint32_t s_creator_os
;
121 grub_uint16_t s_def_resuid
;
122 grub_uint16_t s_def_resgid
;
123 grub_uint32_t s_first_ino
;
124 grub_uint16_t s_inode_size
;
125 grub_uint16_t s_dat_entry_size
;
126 grub_uint16_t s_checkpoint_size
;
127 grub_uint16_t s_segment_usage_size
;
128 grub_uint8_t s_uuid
[16];
129 char s_volume_name
[80];
130 grub_uint32_t s_c_interval
;
131 grub_uint32_t s_c_block_max
;
132 grub_uint32_t s_reserved
[192];
135 struct grub_nilfs2_dir_entry
138 grub_uint16_t rec_len
;
139 #define MAX_NAMELEN 255
140 grub_uint8_t name_len
;
141 grub_uint8_t file_type
;
142 #if 0 /* followed by file name. */
143 char name
[NILFS_NAME_LEN
];
161 struct grub_nilfs2_finfo
163 grub_uint64_t fi_ino
;
164 grub_uint64_t fi_cno
;
165 grub_uint32_t fi_nblocks
;
166 grub_uint32_t fi_ndatablk
;
169 struct grub_nilfs2_binfo_v
171 grub_uint64_t bi_vblocknr
;
172 grub_uint64_t bi_blkoff
;
175 struct grub_nilfs2_binfo_dat
177 grub_uint64_t bi_blkoff
;
178 grub_uint8_t bi_level
;
179 grub_uint8_t bi_pad
[7];
182 union grub_nilfs2_binfo
184 struct grub_nilfs2_binfo_v bi_v
;
185 struct grub_nilfs2_binfo_dat bi_dat
;
188 struct grub_nilfs2_segment_summary
190 grub_uint32_t ss_datasum
;
191 grub_uint32_t ss_sumsum
;
192 grub_uint32_t ss_magic
;
193 grub_uint16_t ss_bytes
;
194 grub_uint16_t ss_flags
;
195 grub_uint64_t ss_seq
;
196 grub_uint64_t ss_create
;
197 grub_uint64_t ss_next
;
198 grub_uint32_t ss_nblocks
;
199 grub_uint32_t ss_nfinfo
;
200 grub_uint32_t ss_sumbytes
;
201 grub_uint32_t ss_pad
;
204 struct grub_nilfs2_btree_node
206 grub_uint8_t bn_flags
;
207 grub_uint8_t bn_level
;
208 grub_uint16_t bn_nchildren
;
209 grub_uint32_t bn_pad
;
210 grub_uint64_t keys
[0];
213 struct grub_nilfs2_palloc_group_desc
215 grub_uint32_t pg_nfrees
;
218 #define LOG_SIZE_GROUP_DESC 2
220 #define LOG_NILFS_DAT_ENTRY_SIZE 5
221 struct grub_nilfs2_dat_entry
223 grub_uint64_t de_blocknr
;
224 grub_uint64_t de_start
;
225 grub_uint64_t de_end
;
226 grub_uint64_t de_rsv
;
229 struct grub_nilfs2_snapshot_list
231 grub_uint64_t ssl_next
;
232 grub_uint64_t ssl_prev
;
235 struct grub_nilfs2_cpfile_header
237 grub_uint64_t ch_ncheckpoints
;
238 grub_uint64_t ch_nsnapshots
;
239 struct grub_nilfs2_snapshot_list ch_snapshot_list
;
242 struct grub_nilfs2_checkpoint
244 grub_uint32_t cp_flags
;
245 grub_uint32_t cp_checkpoints_count
;
246 struct grub_nilfs2_snapshot_list cp_snapshot_list
;
247 grub_uint64_t cp_cno
;
248 grub_uint64_t cp_create
;
249 grub_uint64_t cp_nblk_inc
;
250 grub_uint64_t cp_inodes_count
;
251 grub_uint64_t cp_blocks_count
;
252 struct grub_nilfs2_inode cp_ifile_inode
;
256 #define NILFS_BMAP_LARGE 0x1
257 #define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(grub_uint64_t))
259 /* nilfs extra padding for nonroot btree node. */
260 #define NILFS_BTREE_NODE_EXTRA_PAD_SIZE (sizeof(grub_uint64_t))
261 #define NILFS_BTREE_ROOT_SIZE NILFS_BMAP_SIZE
262 #define NILFS_BTREE_ROOT_NCHILDREN_MAX \
263 ((NILFS_BTREE_ROOT_SIZE - sizeof(struct nilfs_btree_node)) / \
264 (sizeof(grub_uint64_t) + sizeof(grub_uint64_t)) )
267 struct grub_fshelp_node
269 struct grub_nilfs2_data
*data
;
270 struct grub_nilfs2_inode inode
;
275 struct grub_nilfs2_data
277 struct grub_nilfs2_super_block sblock
;
278 struct grub_nilfs2_super_root sroot
;
279 struct grub_nilfs2_inode ifile
;
281 struct grub_nilfs2_inode
*inode
;
282 struct grub_fshelp_node diropen
;
285 /* Log2 size of nilfs2 block in 512 blocks. */
286 #define LOG2_NILFS2_BLOCK_SIZE(data) \
287 (grub_le_to_cpu32 (data->sblock.s_log_block_size) + 1)
289 /* Log2 size of nilfs2 block in bytes. */
290 #define LOG2_BLOCK_SIZE(data) \
291 (grub_le_to_cpu32 (data->sblock.s_log_block_size) + 10)
293 /* The size of an nilfs2 block in bytes. */
294 #define NILFS2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data))
297 grub_nilfs2_dat_translate (struct grub_nilfs2_data
*data
, grub_uint64_t key
);
298 static grub_dl_t my_mod
;
302 static inline unsigned long
303 grub_nilfs2_log_palloc_entries_per_group (struct grub_nilfs2_data
*data
)
305 return LOG2_BLOCK_SIZE (data
) + 3;
308 static inline grub_uint64_t
309 grub_nilfs2_palloc_group (struct grub_nilfs2_data
*data
,
310 grub_uint64_t nr
, grub_uint64_t
* offset
)
312 *offset
= nr
& ((1 << grub_nilfs2_log_palloc_entries_per_group (data
)) - 1);
313 return nr
>> grub_nilfs2_log_palloc_entries_per_group (data
);
316 static inline grub_uint32_t
317 grub_nilfs2_palloc_log_groups_per_desc_block (struct grub_nilfs2_data
*data
)
319 return LOG2_BLOCK_SIZE (data
) - LOG_SIZE_GROUP_DESC
;
321 COMPILE_TIME_ASSERT (sizeof (struct grub_nilfs2_palloc_group_desc
)
322 == (1 << LOG_SIZE_GROUP_DESC
));
325 static inline grub_uint32_t
326 grub_nilfs2_log_entries_per_block_log (struct grub_nilfs2_data
*data
,
327 unsigned long log_entry_size
)
329 return LOG2_BLOCK_SIZE (data
) - log_entry_size
;
333 static inline grub_uint32_t
334 grub_nilfs2_blocks_per_group_log (struct grub_nilfs2_data
*data
,
335 unsigned long log_entry_size
)
337 return (1 << (grub_nilfs2_log_palloc_entries_per_group (data
)
338 - grub_nilfs2_log_entries_per_block_log (data
,
339 log_entry_size
))) + 1;
342 static inline grub_uint32_t
343 grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data
*data
,
344 unsigned long log_entry_size
)
346 return(grub_nilfs2_blocks_per_group_log (data
, log_entry_size
)
347 << grub_nilfs2_palloc_log_groups_per_desc_block (data
)) + 1;
350 static inline grub_uint32_t
351 grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data
*data
,
353 unsigned long log_entry_size
)
355 grub_uint32_t desc_block
=
356 group
>> grub_nilfs2_palloc_log_groups_per_desc_block (data
);
357 return desc_block
* grub_nilfs2_blocks_per_desc_block_log (data
,
361 static inline grub_uint32_t
362 grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data
*data
,
364 unsigned long log_entry_size
)
366 unsigned long desc_offset
= group
367 & ((1 << grub_nilfs2_palloc_log_groups_per_desc_block (data
)) - 1);
369 return grub_nilfs2_palloc_desc_block_offset_log (data
, group
, log_entry_size
)
371 + desc_offset
* grub_nilfs2_blocks_per_group_log (data
, log_entry_size
);
374 static inline grub_uint32_t
375 grub_nilfs2_palloc_entry_offset_log (struct grub_nilfs2_data
*data
,
377 unsigned long log_entry_size
)
380 grub_uint64_t group_offset
;
382 group
= grub_nilfs2_palloc_group (data
, nr
, &group_offset
);
384 return grub_nilfs2_palloc_bitmap_block_offset (data
, group
,
385 log_entry_size
) + 1 +
386 (group_offset
>> grub_nilfs2_log_entries_per_block_log (data
,
391 static inline struct grub_nilfs2_btree_node
*
392 grub_nilfs2_btree_get_root (struct grub_nilfs2_inode
*inode
)
394 return (struct grub_nilfs2_btree_node
*) &inode
->i_bmap
[0];
398 grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node
*node
)
400 return node
->bn_level
;
403 static inline grub_uint64_t
*
404 grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node
*node
)
407 ((node
->bn_flags
& NILFS_BTREE_NODE_ROOT
) ?
408 0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE
/ sizeof (grub_uint64_t
))));
411 static inline grub_uint64_t
412 grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node
*node
,
415 return grub_le_to_cpu64 (*(grub_nilfs2_btree_node_dkeys (node
) + index
));
419 grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data
*data
,
420 struct grub_nilfs2_btree_node
*node
)
422 int node_children_max
= ((NILFS2_BLOCK_SIZE (data
) -
423 sizeof (struct grub_nilfs2_btree_node
) -
424 NILFS_BTREE_NODE_EXTRA_PAD_SIZE
) /
425 (sizeof (grub_uint64_t
) + sizeof (grub_uint64_t
)));
427 return (node
->bn_flags
& NILFS_BTREE_NODE_ROOT
) ? 3 : node_children_max
;
431 grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data
*data
,
432 struct grub_nilfs2_btree_node
*node
,
433 grub_uint64_t key
, int *indexp
)
436 int index
= 0, low
, high
, s
;
440 high
= grub_le_to_cpu16 (node
->bn_nchildren
) - 1;
441 if (high
>= grub_nilfs2_btree_node_nchildren_max (data
, node
))
443 grub_error (GRUB_ERR_BAD_FS
, "too many children");
451 index
= (low
+ high
) / 2;
452 nkey
= grub_nilfs2_btree_node_get_key (node
, index
);
470 if (node
->bn_level
> NILFS_BTREE_LEVEL_NODE_MIN
)
472 if (s
> 0 && index
> 0)
482 static inline grub_uint64_t
*
483 grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data
*data
,
484 struct grub_nilfs2_btree_node
*node
)
486 return (grub_uint64_t
*) (grub_nilfs2_btree_node_dkeys (node
) +
487 grub_nilfs2_btree_node_nchildren_max (data
,
491 static inline grub_uint64_t
492 grub_nilfs2_btree_node_get_ptr (struct grub_nilfs2_data
*data
,
493 struct grub_nilfs2_btree_node
*node
,
497 grub_le_to_cpu64 (*(grub_nilfs2_btree_node_dptrs (data
, node
) + index
));
501 grub_nilfs2_btree_get_nonroot_node (struct grub_nilfs2_data
*data
,
502 grub_uint64_t ptr
, void *block
)
504 grub_disk_t disk
= data
->disk
;
505 unsigned int nilfs2_block_count
= (1 << LOG2_NILFS2_BLOCK_SIZE (data
));
507 return grub_disk_read (disk
, ptr
* nilfs2_block_count
, 0,
508 NILFS2_BLOCK_SIZE (data
), block
);
512 grub_nilfs2_btree_lookup (struct grub_nilfs2_data
*data
,
513 struct grub_nilfs2_inode
*inode
,
514 grub_uint64_t key
, int need_translate
)
516 struct grub_nilfs2_btree_node
*node
;
519 int level
, found
= 0, index
;
521 block
= grub_malloc (NILFS2_BLOCK_SIZE (data
));
525 node
= grub_nilfs2_btree_get_root (inode
);
526 level
= grub_nilfs2_btree_get_level (node
);
528 found
= grub_nilfs2_btree_node_lookup (data
, node
, key
, &index
);
530 if (grub_errno
!= GRUB_ERR_NONE
)
533 ptr
= grub_nilfs2_btree_node_get_ptr (data
, node
, index
);
535 ptr
= grub_nilfs2_dat_translate (data
, ptr
);
537 for (level
--; level
>= NILFS_BTREE_LEVEL_NODE_MIN
; level
--)
539 grub_nilfs2_btree_get_nonroot_node (data
, ptr
, block
);
544 node
= (struct grub_nilfs2_btree_node
*) block
;
546 if (node
->bn_level
!= level
)
548 grub_error (GRUB_ERR_BAD_FS
, "btree level mismatch\n");
553 found
= grub_nilfs2_btree_node_lookup (data
, node
, key
, &index
);
557 if (index
< grub_nilfs2_btree_node_nchildren_max (data
, node
) &&
558 grub_errno
== GRUB_ERR_NONE
)
560 ptr
= grub_nilfs2_btree_node_get_ptr (data
, node
, index
);
562 ptr
= grub_nilfs2_dat_translate (data
, ptr
);
566 grub_error (GRUB_ERR_BAD_FS
, "btree corruption\n");
582 static inline grub_uint64_t
583 grub_nilfs2_direct_lookup (struct grub_nilfs2_inode
*inode
, grub_uint64_t key
)
587 grub_error (GRUB_ERR_BAD_FS
, "key is too large");
588 return 0xffffffffffffffff;
590 return grub_le_to_cpu64 (inode
->i_bmap
[1 + key
]);
593 static inline grub_uint64_t
594 grub_nilfs2_bmap_lookup (struct grub_nilfs2_data
*data
,
595 struct grub_nilfs2_inode
*inode
,
596 grub_uint64_t key
, int need_translate
)
598 struct grub_nilfs2_btree_node
*root
= grub_nilfs2_btree_get_root (inode
);
599 if (root
->bn_flags
& NILFS_BMAP_LARGE
)
600 return grub_nilfs2_btree_lookup (data
, inode
, key
, need_translate
);
604 ptr
= grub_nilfs2_direct_lookup (inode
, key
);
605 if (ptr
!= ((grub_uint64_t
) 0xffffffffffffffff) && need_translate
)
606 ptr
= grub_nilfs2_dat_translate (data
, ptr
);
612 grub_nilfs2_dat_translate (struct grub_nilfs2_data
*data
, grub_uint64_t key
)
614 struct grub_nilfs2_dat_entry entry
;
615 grub_disk_t disk
= data
->disk
;
617 grub_uint64_t blockno
, offset
;
618 unsigned int nilfs2_block_count
= (1 << LOG2_NILFS2_BLOCK_SIZE (data
));
620 blockno
= grub_nilfs2_palloc_entry_offset_log (data
, key
,
621 LOG_NILFS_DAT_ENTRY_SIZE
);
623 offset
= ((key
* sizeof (struct grub_nilfs2_dat_entry
))
624 & ((1 << LOG2_BLOCK_SIZE (data
)) - 1));
626 pptr
= grub_nilfs2_bmap_lookup (data
, &data
->sroot
.sr_dat
, blockno
, 0);
627 if (pptr
== (grub_uint64_t
) - 1)
629 grub_error (GRUB_ERR_BAD_FS
, "btree lookup failure");
633 grub_disk_read (disk
, pptr
* nilfs2_block_count
, offset
,
634 sizeof (struct grub_nilfs2_dat_entry
), &entry
);
636 return grub_le_to_cpu64 (entry
.de_blocknr
);
640 static grub_disk_addr_t
641 grub_nilfs2_read_block (grub_fshelp_node_t node
, grub_disk_addr_t fileblock
)
643 struct grub_nilfs2_data
*data
= node
->data
;
644 struct grub_nilfs2_inode
*inode
= &node
->inode
;
645 grub_uint64_t pptr
= -1;
647 pptr
= grub_nilfs2_bmap_lookup (data
, inode
, fileblock
, 1);
648 if (pptr
== (grub_uint64_t
) - 1)
650 grub_error (GRUB_ERR_BAD_FS
, "btree lookup failure");
657 /* Read LEN bytes from the file described by DATA starting with byte
658 POS. Return the amount of read bytes in READ. */
660 grub_nilfs2_read_file (grub_fshelp_node_t node
,
661 grub_disk_read_hook_t read_hook
, void *read_hook_data
,
662 grub_off_t pos
, grub_size_t len
, char *buf
)
664 return grub_fshelp_read_file (node
->data
->disk
, node
,
665 read_hook
, read_hook_data
,
666 pos
, len
, buf
, grub_nilfs2_read_block
,
667 grub_le_to_cpu64 (node
->inode
.i_size
),
668 LOG2_NILFS2_BLOCK_SIZE (node
->data
), 0);
673 grub_nilfs2_read_checkpoint (struct grub_nilfs2_data
*data
,
675 struct grub_nilfs2_checkpoint
*cpp
)
677 grub_uint64_t blockno
;
678 grub_uint64_t offset
;
680 grub_disk_t disk
= data
->disk
;
681 unsigned int nilfs2_block_count
= (1 << LOG2_NILFS2_BLOCK_SIZE (data
));
683 /* Assume sizeof(struct grub_nilfs2_cpfile_header) <
684 sizeof(struct grub_nilfs2_checkpoint).
686 blockno
= grub_divmod64 (cpno
, NILFS2_BLOCK_SIZE (data
) /
687 sizeof (struct grub_nilfs2_checkpoint
), &offset
);
689 pptr
= grub_nilfs2_bmap_lookup (data
, &data
->sroot
.sr_cpfile
, blockno
, 1);
690 if (pptr
== (grub_uint64_t
) - 1)
692 return grub_error (GRUB_ERR_BAD_FS
, "btree lookup failure");
695 return grub_disk_read (disk
, pptr
* nilfs2_block_count
,
696 offset
* sizeof (struct grub_nilfs2_checkpoint
),
697 sizeof (struct grub_nilfs2_checkpoint
), cpp
);
700 static inline grub_err_t
701 grub_nilfs2_read_last_checkpoint (struct grub_nilfs2_data
*data
,
702 struct grub_nilfs2_checkpoint
*cpp
)
704 return grub_nilfs2_read_checkpoint (data
,
705 grub_le_to_cpu64 (data
->
710 /* Read the inode INO for the file described by DATA into INODE. */
712 grub_nilfs2_read_inode (struct grub_nilfs2_data
*data
,
713 grub_uint64_t ino
, struct grub_nilfs2_inode
*inodep
)
715 grub_uint64_t blockno
;
716 grub_uint64_t offset
;
718 grub_disk_t disk
= data
->disk
;
719 unsigned int nilfs2_block_count
= (1 << LOG2_NILFS2_BLOCK_SIZE (data
));
721 blockno
= grub_nilfs2_palloc_entry_offset_log (data
, ino
,
724 offset
= ((sizeof (struct grub_nilfs2_inode
) * ino
)
725 & ((1 << LOG2_BLOCK_SIZE (data
)) - 1));
726 pptr
= grub_nilfs2_bmap_lookup (data
, &data
->ifile
, blockno
, 1);
727 if (pptr
== (grub_uint64_t
) - 1)
729 return grub_error (GRUB_ERR_BAD_FS
, "btree lookup failure");
732 return grub_disk_read (disk
, pptr
* nilfs2_block_count
, offset
,
733 sizeof (struct grub_nilfs2_inode
), inodep
);
737 grub_nilfs2_valid_sb (struct grub_nilfs2_super_block
*sbp
)
739 if (grub_le_to_cpu16 (sbp
->s_magic
) != NILFS2_SUPER_MAGIC
)
742 if (grub_le_to_cpu32 (sbp
->s_rev_level
) != NILFS_SUPORT_REV
)
745 /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */
746 if (grub_le_to_cpu32 (sbp
->s_log_block_size
) > 20)
753 grub_nilfs2_load_sb (struct grub_nilfs2_data
*data
)
755 grub_disk_t disk
= data
->disk
;
756 struct grub_nilfs2_super_block sb2
;
757 grub_uint64_t partition_size
;
762 /* Read first super block. */
763 err
= grub_disk_read (disk
, NILFS_1ST_SUPER_BLOCK
, 0,
764 sizeof (struct grub_nilfs2_super_block
), &data
->sblock
);
767 /* Make sure if 1st super block is valid. */
768 valid
[0] = grub_nilfs2_valid_sb (&data
->sblock
);
771 partition_size
= (grub_le_to_cpu64 (data
->sblock
.s_dev_size
)
772 >> GRUB_DISK_SECTOR_BITS
);
774 partition_size
= grub_disk_native_sectors (disk
);
775 if (partition_size
!= GRUB_DISK_SIZE_UNKNOWN
)
777 /* Read second super block. */
778 err
= grub_disk_read (disk
, NILFS_2ND_SUPER_BLOCK (partition_size
), 0,
779 sizeof (struct grub_nilfs2_super_block
), &sb2
);
783 grub_errno
= GRUB_ERR_NONE
;
786 /* Make sure if 2nd super block is valid. */
787 valid
[1] = grub_nilfs2_valid_sb (&sb2
);
790 /* 2nd super block may not exist, so it's invalid. */
793 if (!valid
[0] && !valid
[1])
794 return grub_error (GRUB_ERR_BAD_FS
, "not a nilfs2 filesystem");
796 swp
= valid
[1] && (!valid
[0] ||
797 grub_le_to_cpu64 (data
->sblock
.s_last_cno
) <
798 grub_le_to_cpu64 (sb2
.s_last_cno
));
800 /* swap if first super block is invalid or older than second one. */
802 grub_memcpy (&data
->sblock
, &sb2
,
803 sizeof (struct grub_nilfs2_super_block
));
805 return GRUB_ERR_NONE
;
808 static struct grub_nilfs2_data
*
809 grub_nilfs2_mount (grub_disk_t disk
)
811 struct grub_nilfs2_data
*data
;
812 struct grub_nilfs2_segment_summary ss
;
813 struct grub_nilfs2_checkpoint last_checkpoint
;
814 grub_uint64_t last_pseg
;
815 grub_uint32_t nblocks
;
816 unsigned int nilfs2_block_count
;
818 data
= grub_malloc (sizeof (struct grub_nilfs2_data
));
824 /* Read the superblock. */
825 grub_nilfs2_load_sb (data
);
829 nilfs2_block_count
= (1 << LOG2_NILFS2_BLOCK_SIZE (data
));
831 /* Read the last segment summary. */
832 last_pseg
= grub_le_to_cpu64 (data
->sblock
.s_last_pseg
);
833 grub_disk_read (disk
, last_pseg
* nilfs2_block_count
, 0,
834 sizeof (struct grub_nilfs2_segment_summary
), &ss
);
839 /* Read the super root block. */
840 nblocks
= grub_le_to_cpu32 (ss
.ss_nblocks
);
841 grub_disk_read (disk
, (last_pseg
+ (nblocks
- 1)) * nilfs2_block_count
, 0,
842 sizeof (struct grub_nilfs2_super_root
), &data
->sroot
);
847 grub_nilfs2_read_last_checkpoint (data
, &last_checkpoint
);
852 grub_memcpy (&data
->ifile
, &last_checkpoint
.cp_ifile_inode
,
853 sizeof (struct grub_nilfs2_inode
));
855 data
->diropen
.data
= data
;
856 data
->diropen
.ino
= 2;
857 data
->diropen
.inode_read
= 1;
858 data
->inode
= &data
->diropen
.inode
;
860 grub_nilfs2_read_inode (data
, 2, data
->inode
);
865 if (grub_errno
== GRUB_ERR_OUT_OF_RANGE
)
866 grub_error (GRUB_ERR_BAD_FS
, "not a nilfs2 filesystem");
873 grub_nilfs2_read_symlink (grub_fshelp_node_t node
)
876 struct grub_fshelp_node
*diro
= node
;
878 if (!diro
->inode_read
)
880 grub_nilfs2_read_inode (diro
->data
, diro
->ino
, &diro
->inode
);
885 symlink
= grub_malloc (grub_le_to_cpu64 (diro
->inode
.i_size
) + 1);
889 grub_nilfs2_read_file (diro
, 0, 0, 0,
890 grub_le_to_cpu64 (diro
->inode
.i_size
), symlink
);
897 symlink
[grub_le_to_cpu64 (diro
->inode
.i_size
)] = '\0';
902 grub_nilfs2_iterate_dir (grub_fshelp_node_t dir
,
903 grub_fshelp_iterate_dir_hook_t hook
, void *hook_data
)
906 struct grub_fshelp_node
*diro
= (struct grub_fshelp_node
*) dir
;
908 if (!diro
->inode_read
)
910 grub_nilfs2_read_inode (diro
->data
, diro
->ino
, &diro
->inode
);
916 while (fpos
< grub_le_to_cpu64 (diro
->inode
.i_size
))
918 struct grub_nilfs2_dir_entry dirent
;
920 grub_nilfs2_read_file (diro
, 0, 0, fpos
,
921 sizeof (struct grub_nilfs2_dir_entry
),
926 if (dirent
.rec_len
== 0)
929 if (dirent
.name_len
!= 0)
931 char filename
[MAX_NAMELEN
+ 1];
932 struct grub_fshelp_node
*fdiro
;
933 enum grub_fshelp_filetype type
= GRUB_FSHELP_UNKNOWN
;
935 grub_nilfs2_read_file (diro
, 0, 0,
936 fpos
+ sizeof (struct grub_nilfs2_dir_entry
),
937 dirent
.name_len
, filename
);
941 fdiro
= grub_malloc (sizeof (struct grub_fshelp_node
));
945 fdiro
->data
= diro
->data
;
946 fdiro
->ino
= grub_le_to_cpu64 (dirent
.inode
);
948 filename
[dirent
.name_len
] = '\0';
950 if (dirent
.file_type
!= NILFS_FT_UNKNOWN
)
952 fdiro
->inode_read
= 0;
954 if (dirent
.file_type
== NILFS_FT_DIR
)
955 type
= GRUB_FSHELP_DIR
;
956 else if (dirent
.file_type
== NILFS_FT_SYMLINK
)
957 type
= GRUB_FSHELP_SYMLINK
;
958 else if (dirent
.file_type
== NILFS_FT_REG_FILE
)
959 type
= GRUB_FSHELP_REG
;
963 /* The filetype can not be read from the dirent, read
964 the inode to get more information. */
965 grub_nilfs2_read_inode (diro
->data
,
966 grub_le_to_cpu64 (dirent
.inode
),
974 fdiro
->inode_read
= 1;
976 if ((grub_le_to_cpu16 (fdiro
->inode
.i_mode
)
977 & FILETYPE_INO_MASK
) == FILETYPE_INO_DIRECTORY
)
978 type
= GRUB_FSHELP_DIR
;
979 else if ((grub_le_to_cpu16 (fdiro
->inode
.i_mode
)
980 & FILETYPE_INO_MASK
) == FILETYPE_INO_SYMLINK
)
981 type
= GRUB_FSHELP_SYMLINK
;
982 else if ((grub_le_to_cpu16 (fdiro
->inode
.i_mode
)
983 & FILETYPE_INO_MASK
) == FILETYPE_INO_REG
)
984 type
= GRUB_FSHELP_REG
;
987 if (hook (filename
, type
, fdiro
, hook_data
))
991 fpos
+= grub_le_to_cpu16 (dirent
.rec_len
);
997 /* Open a file named NAME and initialize FILE. */
999 grub_nilfs2_open (struct grub_file
*file
, const char *name
)
1001 struct grub_nilfs2_data
*data
= NULL
;
1002 struct grub_fshelp_node
*fdiro
= 0;
1004 grub_dl_ref (my_mod
);
1006 data
= grub_nilfs2_mount (file
->device
->disk
);
1010 grub_fshelp_find_file (name
, &data
->diropen
, &fdiro
,
1011 grub_nilfs2_iterate_dir
, grub_nilfs2_read_symlink
,
1016 if (!fdiro
->inode_read
)
1018 grub_nilfs2_read_inode (data
, fdiro
->ino
, &fdiro
->inode
);
1023 grub_memcpy (data
->inode
, &fdiro
->inode
, sizeof (struct grub_nilfs2_inode
));
1026 file
->size
= grub_le_to_cpu64 (data
->inode
->i_size
);
1033 if (fdiro
!= &data
->diropen
)
1037 grub_dl_unref (my_mod
);
1043 grub_nilfs2_close (grub_file_t file
)
1045 grub_free (file
->data
);
1047 grub_dl_unref (my_mod
);
1049 return GRUB_ERR_NONE
;
1052 /* Read LEN bytes data from FILE into BUF. */
1054 grub_nilfs2_read (grub_file_t file
, char *buf
, grub_size_t len
)
1056 struct grub_nilfs2_data
*data
= (struct grub_nilfs2_data
*) file
->data
;
1058 return grub_nilfs2_read_file (&data
->diropen
,
1059 file
->read_hook
, file
->read_hook_data
,
1060 file
->offset
, len
, buf
);
1063 /* Context for grub_nilfs2_dir. */
1064 struct grub_nilfs2_dir_ctx
1066 grub_fs_dir_hook_t hook
;
1068 struct grub_nilfs2_data
*data
;
1071 /* Helper for grub_nilfs2_dir. */
1073 grub_nilfs2_dir_iter (const char *filename
, enum grub_fshelp_filetype filetype
,
1074 grub_fshelp_node_t node
, void *data
)
1076 struct grub_nilfs2_dir_ctx
*ctx
= data
;
1077 struct grub_dirhook_info info
;
1079 grub_memset (&info
, 0, sizeof (info
));
1080 if (!node
->inode_read
)
1082 grub_nilfs2_read_inode (ctx
->data
, node
->ino
, &node
->inode
);
1084 node
->inode_read
= 1;
1085 grub_errno
= GRUB_ERR_NONE
;
1087 if (node
->inode_read
)
1090 info
.mtime
= grub_le_to_cpu64 (node
->inode
.i_mtime
);
1093 info
.dir
= ((filetype
& GRUB_FSHELP_TYPE_MASK
) == GRUB_FSHELP_DIR
);
1095 return ctx
->hook (filename
, &info
, ctx
->hook_data
);
1099 grub_nilfs2_dir (grub_device_t device
, const char *path
,
1100 grub_fs_dir_hook_t hook
, void *hook_data
)
1102 struct grub_nilfs2_dir_ctx ctx
= {
1104 .hook_data
= hook_data
1106 struct grub_fshelp_node
*fdiro
= 0;
1108 grub_dl_ref (my_mod
);
1110 ctx
.data
= grub_nilfs2_mount (device
->disk
);
1114 grub_fshelp_find_file (path
, &ctx
.data
->diropen
, &fdiro
,
1115 grub_nilfs2_iterate_dir
, grub_nilfs2_read_symlink
,
1120 grub_nilfs2_iterate_dir (fdiro
, grub_nilfs2_dir_iter
, &ctx
);
1123 if (fdiro
!= &ctx
.data
->diropen
)
1125 grub_free (ctx
.data
);
1127 grub_dl_unref (my_mod
);
1133 grub_nilfs2_label (grub_device_t device
, char **label
)
1135 struct grub_nilfs2_data
*data
;
1136 grub_disk_t disk
= device
->disk
;
1138 grub_dl_ref (my_mod
);
1140 data
= grub_nilfs2_mount (disk
);
1142 *label
= grub_strndup (data
->sblock
.s_volume_name
,
1143 sizeof (data
->sblock
.s_volume_name
));
1147 grub_dl_unref (my_mod
);
1155 grub_nilfs2_uuid (grub_device_t device
, char **uuid
)
1157 struct grub_nilfs2_data
*data
;
1158 grub_disk_t disk
= device
->disk
;
1160 grub_dl_ref (my_mod
);
1162 data
= grub_nilfs2_mount (disk
);
1167 ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1168 data
->sblock
.s_uuid
[0], data
->sblock
.s_uuid
[1],
1169 data
->sblock
.s_uuid
[2], data
->sblock
.s_uuid
[3],
1170 data
->sblock
.s_uuid
[4], data
->sblock
.s_uuid
[5],
1171 data
->sblock
.s_uuid
[6], data
->sblock
.s_uuid
[7],
1172 data
->sblock
.s_uuid
[8], data
->sblock
.s_uuid
[9],
1173 data
->sblock
.s_uuid
[10], data
->sblock
.s_uuid
[11],
1174 data
->sblock
.s_uuid
[12], data
->sblock
.s_uuid
[13],
1175 data
->sblock
.s_uuid
[14], data
->sblock
.s_uuid
[15]);
1180 grub_dl_unref (my_mod
);
1189 grub_nilfs2_mtime (grub_device_t device
, grub_int64_t
* tm
)
1191 struct grub_nilfs2_data
*data
;
1192 grub_disk_t disk
= device
->disk
;
1194 grub_dl_ref (my_mod
);
1196 data
= grub_nilfs2_mount (disk
);
1200 *tm
= (grub_int32_t
) grub_le_to_cpu64 (data
->sblock
.s_wtime
);
1202 grub_dl_unref (my_mod
);
1211 static struct grub_fs grub_nilfs2_fs
= {
1213 .fs_dir
= grub_nilfs2_dir
,
1214 .fs_open
= grub_nilfs2_open
,
1215 .fs_read
= grub_nilfs2_read
,
1216 .fs_close
= grub_nilfs2_close
,
1217 .fs_label
= grub_nilfs2_label
,
1218 .fs_uuid
= grub_nilfs2_uuid
,
1219 .fs_mtime
= grub_nilfs2_mtime
,
1221 .reserved_first_sector
= 1,
1222 .blocklist_install
= 0,
1227 GRUB_MOD_INIT (nilfs2
)
1229 COMPILE_TIME_ASSERT ((1 << LOG_NILFS_DAT_ENTRY_SIZE
)
1231 grub_nilfs2_dat_entry
));
1232 COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
1233 == sizeof (struct grub_nilfs2_inode
));
1234 grub_fs_register (&grub_nilfs2_fs
);
1238 GRUB_MOD_FINI (nilfs2
)
1240 grub_fs_unregister (&grub_nilfs2_fs
);