~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to fs/nilfs2.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
 *  nilfs2.c - New Implementation of Log filesystem 
3
 
 *
4
 
 *  Written by Jiro SEKIBA <jir@unicus.jp>
5
 
 *
6
 
 *  Copyright (C) 2003,2004,2005,2007,2008,2010  Free Software Foundation, Inc.
7
 
 *
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.
12
 
 *
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.
17
 
 *
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/>.
20
 
 */
21
 
 
22
 
 
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
28
 
 
29
 
#include <grub/err.h>
30
 
#include <grub/file.h>
31
 
#include <grub/mm.h>
32
 
#include <grub/misc.h>
33
 
#include <grub/disk.h>
34
 
#include <grub/dl.h>
35
 
#include <grub/types.h>
36
 
#include <grub/fshelp.h>
37
 
 
38
 
#define NILFS_INODE_BMAP_SIZE   7
39
 
 
40
 
#define NILFS_SUPORT_REV        2
41
 
 
42
 
/* Magic value used to identify an nilfs2 filesystem.  */
43
 
#define NILFS2_SUPER_MAGIC      0x3434
44
 
/* nilfs btree node flag.  */
45
 
#define NILFS_BTREE_NODE_ROOT   0x01
46
 
 
47
 
/* nilfs btree node level. */
48
 
#define NILFS_BTREE_LEVEL_DATA          0
49
 
#define NILFS_BTREE_LEVEL_NODE_MIN      (NILFS_BTREE_LEVEL_DATA + 1)
50
 
#define NILFS_BTREE_LEVEL_MAX           14
51
 
 
52
 
/* nilfs 1st super block posission from beginning of the partition
53
 
   in 512 block size */
54
 
#define NILFS_1ST_SUPER_BLOCK   2
55
 
/* nilfs 2nd super block posission from beginning of the partition
56
 
   in 512 block size */
57
 
#define NILFS_2ND_SUPER_BLOCK(devsize)  (((devsize >> 3) - 1) << 3)
58
 
 
59
 
struct grub_nilfs2_inode
60
 
{
61
 
  grub_uint64_t i_blocks;
62
 
  grub_uint64_t i_size;
63
 
  grub_uint64_t i_ctime;
64
 
  grub_uint64_t i_mtime;
65
 
  grub_uint32_t i_ctime_nsec;
66
 
  grub_uint32_t i_mtime_nsec;
67
 
  grub_uint32_t i_uid;
68
 
  grub_uint32_t i_gid;
69
 
  grub_uint16_t i_mode;
70
 
  grub_uint16_t i_links_count;
71
 
  grub_uint32_t i_flags;
72
 
  grub_uint64_t i_bmap[NILFS_INODE_BMAP_SIZE];
73
 
#define i_device_code   i_bmap[0]
74
 
  grub_uint64_t i_xattr;
75
 
  grub_uint32_t i_generation;
76
 
  grub_uint32_t i_pad;
77
 
};
78
 
 
79
 
struct grub_nilfs2_super_root
80
 
{
81
 
  grub_uint32_t sr_sum;
82
 
  grub_uint16_t sr_bytes;
83
 
  grub_uint16_t sr_flags;
84
 
  grub_uint64_t sr_nongc_ctime;
85
 
  struct grub_nilfs2_inode sr_dat;
86
 
  struct grub_nilfs2_inode sr_cpfile;
87
 
  struct grub_nilfs2_inode sr_sufile;
88
 
};
89
 
 
90
 
struct grub_nilfs2_super_block
91
 
{
92
 
  grub_uint32_t s_rev_level;
93
 
  grub_uint16_t s_minor_rev_level;
94
 
  grub_uint16_t s_magic;
95
 
  grub_uint16_t s_bytes;
96
 
  grub_uint16_t s_flags;
97
 
  grub_uint32_t s_crc_seed;
98
 
  grub_uint32_t s_sum;
99
 
  grub_uint32_t s_log_block_size;
100
 
  grub_uint64_t s_nsegments;
101
 
  grub_uint64_t s_dev_size;
102
 
  grub_uint64_t s_first_data_block;
103
 
  grub_uint32_t s_blocks_per_segment;
104
 
  grub_uint32_t s_r_segments_percentage;
105
 
  grub_uint64_t s_last_cno;
106
 
  grub_uint64_t s_last_pseg;
107
 
  grub_uint64_t s_last_seq;
108
 
  grub_uint64_t s_free_blocks_count;
109
 
  grub_uint64_t s_ctime;
110
 
  grub_uint64_t s_mtime;
111
 
  grub_uint64_t s_wtime;
112
 
  grub_uint16_t s_mnt_count;
113
 
  grub_uint16_t s_max_mnt_count;
114
 
  grub_uint16_t s_state;
115
 
  grub_uint16_t s_errors;
116
 
  grub_uint64_t s_lastcheck;
117
 
  grub_uint32_t s_checkinterval;
118
 
  grub_uint32_t s_creator_os;
119
 
  grub_uint16_t s_def_resuid;
120
 
  grub_uint16_t s_def_resgid;
121
 
  grub_uint32_t s_first_ino;
122
 
  grub_uint16_t s_inode_size;
123
 
  grub_uint16_t s_dat_entry_size;
124
 
  grub_uint16_t s_checkpoint_size;
125
 
  grub_uint16_t s_segment_usage_size;
126
 
  grub_uint8_t s_uuid[16];
127
 
  char s_volume_name[16];
128
 
  char s_last_mounted[64];
129
 
  grub_uint32_t s_c_interval;
130
 
  grub_uint32_t s_c_block_max;
131
 
  grub_uint32_t s_reserved[192];
132
 
};
133
 
 
134
 
struct grub_nilfs2_dir_entry
135
 
{
136
 
  grub_uint64_t inode;
137
 
  grub_uint16_t rec_len;
138
 
  grub_uint8_t name_len;
139
 
  grub_uint8_t file_type;
140
 
#if 0                           /* followed by file name. */
141
 
  char name[NILFS_NAME_LEN];
142
 
  char pad;
143
 
#endif
144
 
} __attribute__ ((packed));
145
 
 
146
 
enum
147
 
{
148
 
  NILFS_FT_UNKNOWN,
149
 
  NILFS_FT_REG_FILE,
150
 
  NILFS_FT_DIR,
151
 
  NILFS_FT_CHRDEV,
152
 
  NILFS_FT_BLKDEV,
153
 
  NILFS_FT_FIFO,
154
 
  NILFS_FT_SOCK,
155
 
  NILFS_FT_SYMLINK,
156
 
  NILFS_FT_MAX
157
 
};
158
 
 
159
 
struct grub_nilfs2_finfo
160
 
{
161
 
  grub_uint64_t fi_ino;
162
 
  grub_uint64_t fi_cno;
163
 
  grub_uint32_t fi_nblocks;
164
 
  grub_uint32_t fi_ndatablk;
165
 
};
166
 
 
167
 
struct grub_nilfs2_binfo_v
168
 
{
169
 
  grub_uint64_t bi_vblocknr;
170
 
  grub_uint64_t bi_blkoff;
171
 
};
172
 
 
173
 
struct grub_nilfs2_binfo_dat
174
 
{
175
 
  grub_uint64_t bi_blkoff;
176
 
  grub_uint8_t bi_level;
177
 
  grub_uint8_t bi_pad[7];
178
 
};
179
 
 
180
 
union grub_nilfs2_binfo
181
 
{
182
 
  struct grub_nilfs2_binfo_v bi_v;
183
 
  struct grub_nilfs2_binfo_dat bi_dat;
184
 
};
185
 
 
186
 
struct grub_nilfs2_segment_summary
187
 
{
188
 
  grub_uint32_t ss_datasum;
189
 
  grub_uint32_t ss_sumsum;
190
 
  grub_uint32_t ss_magic;
191
 
  grub_uint16_t ss_bytes;
192
 
  grub_uint16_t ss_flags;
193
 
  grub_uint64_t ss_seq;
194
 
  grub_uint64_t ss_create;
195
 
  grub_uint64_t ss_next;
196
 
  grub_uint32_t ss_nblocks;
197
 
  grub_uint32_t ss_nfinfo;
198
 
  grub_uint32_t ss_sumbytes;
199
 
  grub_uint32_t ss_pad;
200
 
};
201
 
 
202
 
struct grub_nilfs2_btree_node
203
 
{
204
 
  grub_uint8_t bn_flags;
205
 
  grub_uint8_t bn_level;
206
 
  grub_uint16_t bn_nchildren;
207
 
  grub_uint32_t bn_pad;
208
 
};
209
 
 
210
 
struct grub_nilfs2_palloc_group_desc
211
 
{
212
 
  grub_uint32_t pg_nfrees;
213
 
};
214
 
 
215
 
struct grub_nilfs2_dat_entry
216
 
{
217
 
  grub_uint64_t de_blocknr;
218
 
  grub_uint64_t de_start;
219
 
  grub_uint64_t de_end;
220
 
  grub_uint64_t de_rsv;
221
 
};
222
 
 
223
 
struct grub_nilfs2_snapshot_list
224
 
{
225
 
  grub_uint64_t ssl_next;
226
 
  grub_uint64_t ssl_prev;
227
 
};
228
 
 
229
 
struct grub_nilfs2_cpfile_header
230
 
{
231
 
  grub_uint64_t ch_ncheckpoints;
232
 
  grub_uint64_t ch_nsnapshots;
233
 
  struct grub_nilfs2_snapshot_list ch_snapshot_list;
234
 
};
235
 
 
236
 
struct grub_nilfs2_checkpoint
237
 
{
238
 
  grub_uint32_t cp_flags;
239
 
  grub_uint32_t cp_checkpoints_count;
240
 
  struct grub_nilfs2_snapshot_list cp_snapshot_list;
241
 
  grub_uint64_t cp_cno;
242
 
  grub_uint64_t cp_create;
243
 
  grub_uint64_t cp_nblk_inc;
244
 
  grub_uint64_t cp_inodes_count;
245
 
  grub_uint64_t cp_blocks_count;
246
 
  struct grub_nilfs2_inode cp_ifile_inode;
247
 
};
248
 
 
249
 
 
250
 
#define NILFS_BMAP_LARGE        0x1
251
 
#define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(grub_uint64_t))
252
 
 
253
 
/* nilfs extra padding for nonroot btree node. */
254
 
#define NILFS_BTREE_NODE_EXTRA_PAD_SIZE (sizeof(grub_uint64_t))
255
 
#define NILFS_BTREE_ROOT_SIZE   NILFS_BMAP_SIZE
256
 
#define NILFS_BTREE_ROOT_NCHILDREN_MAX \
257
 
 ((NILFS_BTREE_ROOT_SIZE - sizeof(struct nilfs_btree_node)) / \
258
 
  (sizeof(grub_uint64_t) + sizeof(grub_uint64_t)) )
259
 
 
260
 
 
261
 
struct grub_fshelp_node
262
 
{
263
 
  struct grub_nilfs2_data *data;
264
 
  struct grub_nilfs2_inode inode;
265
 
  grub_uint64_t ino;
266
 
  int inode_read;
267
 
};
268
 
 
269
 
struct grub_nilfs2_data
270
 
{
271
 
  struct grub_nilfs2_super_block sblock;
272
 
  struct grub_nilfs2_super_root sroot;
273
 
  struct grub_nilfs2_inode ifile;
274
 
  grub_disk_t disk;
275
 
  struct grub_nilfs2_inode *inode;
276
 
  struct grub_fshelp_node diropen;
277
 
};
278
 
 
279
 
/* Log2 size of nilfs2 block in 512 blocks.  */
280
 
#define LOG2_NILFS2_BLOCK_SIZE(data)                    \
281
 
        (grub_le_to_cpu32 (data->sblock.s_log_block_size) + 1)
282
 
 
283
 
/* Log2 size of nilfs2 block in bytes.  */
284
 
#define LOG2_BLOCK_SIZE(data)                                   \
285
 
        (grub_le_to_cpu32 (data->sblock.s_log_block_size) + 10)
286
 
 
287
 
/* The size of an nilfs2 block in bytes.  */
288
 
#define NILFS2_BLOCK_SIZE(data)         (1 << LOG2_BLOCK_SIZE (data))
289
 
 
290
 
static grub_uint64_t
291
 
grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key);
292
 
static grub_dl_t my_mod;
293
 
 
294
 
 
295
 
 
296
 
static inline unsigned long
297
 
grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data)
298
 
{
299
 
  return 1UL << (LOG2_BLOCK_SIZE (data) + 3);
300
 
}
301
 
 
302
 
static inline grub_uint64_t
303
 
grub_nilfs2_palloc_group (struct grub_nilfs2_data *data,
304
 
                          grub_uint64_t nr, grub_uint32_t * offset)
305
 
{
306
 
  return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data),
307
 
                        offset);
308
 
}
309
 
 
310
 
static inline grub_uint32_t
311
 
grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data)
312
 
{
313
 
  return NILFS2_BLOCK_SIZE (data) /
314
 
    sizeof (struct grub_nilfs2_palloc_group_desc);
315
 
}
316
 
 
317
 
static inline grub_uint32_t
318
 
grub_nilfs2_entries_per_block (struct grub_nilfs2_data *data,
319
 
                               unsigned long entry_size)
320
 
{
321
 
  return NILFS2_BLOCK_SIZE (data) / entry_size;
322
 
}
323
 
 
324
 
 
325
 
static inline grub_uint32_t
326
 
grub_nilfs2_blocks_per_group (struct grub_nilfs2_data *data,
327
 
                              unsigned long entry_size)
328
 
{
329
 
  return grub_div_roundup (grub_nilfs2_palloc_entries_per_group (data),
330
 
                           grub_nilfs2_entries_per_block (data,
331
 
                                                          entry_size)) + 1;
332
 
}
333
 
 
334
 
static inline grub_uint32_t
335
 
grub_nilfs2_blocks_per_desc_block (struct grub_nilfs2_data *data,
336
 
                                   unsigned long entry_size)
337
 
{
338
 
  return grub_nilfs2_palloc_groups_per_desc_block (data) *
339
 
    grub_nilfs2_blocks_per_group (data, entry_size) + 1;
340
 
}
341
 
 
342
 
static inline grub_uint32_t
343
 
grub_nilfs2_palloc_desc_block_offset (struct grub_nilfs2_data *data,
344
 
                                      unsigned long group,
345
 
                                      unsigned long entry_size)
346
 
{
347
 
  grub_uint32_t desc_block =
348
 
    group / grub_nilfs2_palloc_groups_per_desc_block (data);
349
 
  return desc_block * grub_nilfs2_blocks_per_desc_block (data, entry_size);
350
 
}
351
 
 
352
 
static inline grub_uint32_t
353
 
grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data,
354
 
                                        unsigned long group,
355
 
                                        unsigned long entry_size)
356
 
{
357
 
  unsigned long desc_offset = group %
358
 
    grub_nilfs2_palloc_groups_per_desc_block (data);
359
 
 
360
 
  return grub_nilfs2_palloc_desc_block_offset (data, group, entry_size) + 1 +
361
 
    desc_offset * grub_nilfs2_blocks_per_group (data, entry_size);
362
 
}
363
 
 
364
 
static inline grub_uint32_t
365
 
grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
366
 
                                 grub_uint64_t nr, unsigned long entry_size)
367
 
{
368
 
  unsigned long group;
369
 
  grub_uint32_t group_offset;
370
 
 
371
 
  group = grub_nilfs2_palloc_group (data, nr, &group_offset);
372
 
 
373
 
  return grub_nilfs2_palloc_bitmap_block_offset (data, group,
374
 
                                                 entry_size) + 1 +
375
 
    group_offset / grub_nilfs2_entries_per_block (data, entry_size);
376
 
 
377
 
}
378
 
 
379
 
static inline struct grub_nilfs2_btree_node *
380
 
grub_nilfs2_btree_get_root (struct grub_nilfs2_inode *inode)
381
 
{
382
 
  return (struct grub_nilfs2_btree_node *) &inode->i_bmap[0];
383
 
}
384
 
 
385
 
static inline int
386
 
grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node *node)
387
 
{
388
 
  return node->bn_level;
389
 
}
390
 
 
391
 
static inline grub_uint64_t *
392
 
grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node)
393
 
{
394
 
  return (grub_uint64_t *) ((char *) (node + 1) +
395
 
                            ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ?
396
 
                             0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
397
 
}
398
 
 
399
 
static inline grub_uint64_t
400
 
grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node *node,
401
 
                                int index)
402
 
{
403
 
  return grub_le_to_cpu64 (*(grub_nilfs2_btree_node_dkeys (node) + index));
404
 
}
405
 
 
406
 
static inline int
407
 
grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node,
408
 
                               grub_uint64_t key, int *indexp)
409
 
{
410
 
  grub_uint64_t nkey;
411
 
  int index, low, high, s;
412
 
 
413
 
  low = 0;
414
 
  high = grub_le_to_cpu16 (node->bn_nchildren) - 1;
415
 
  index = 0;
416
 
  s = 0;
417
 
  while (low <= high)
418
 
    {
419
 
      index = (low + high) / 2;
420
 
      nkey = grub_nilfs2_btree_node_get_key (node, index);
421
 
      if (nkey == key)
422
 
        {
423
 
          *indexp = index;
424
 
          return 1;
425
 
        }
426
 
      else if (nkey < key)
427
 
        {
428
 
          low = index + 1;
429
 
          s = -1;
430
 
        }
431
 
      else
432
 
        {
433
 
          high = index - 1;
434
 
          s = 1;
435
 
        }
436
 
    }
437
 
 
438
 
  if (node->bn_level > NILFS_BTREE_LEVEL_NODE_MIN)
439
 
    {
440
 
      if (s > 0 && index > 0)
441
 
        index--;
442
 
    }
443
 
  else if (s < 0)
444
 
    index++;
445
 
 
446
 
  *indexp = index;
447
 
  return s == 0;
448
 
}
449
 
 
450
 
static inline int
451
 
grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data,
452
 
                                      struct grub_nilfs2_btree_node *node)
453
 
{
454
 
  int node_children_max = ((NILFS2_BLOCK_SIZE (data) -
455
 
                            sizeof (struct grub_nilfs2_btree_node) -
456
 
                            NILFS_BTREE_NODE_EXTRA_PAD_SIZE) /
457
 
                           (sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
458
 
 
459
 
  return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max;
460
 
}
461
 
 
462
 
static inline grub_uint64_t *
463
 
grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data *data,
464
 
                              struct grub_nilfs2_btree_node *node)
465
 
{
466
 
  return (grub_uint64_t *) (grub_nilfs2_btree_node_dkeys (node) +
467
 
                            grub_nilfs2_btree_node_nchildren_max (data,
468
 
                                                                  node));
469
 
}
470
 
 
471
 
static inline grub_uint64_t
472
 
grub_nilfs2_btree_node_get_ptr (struct grub_nilfs2_data *data,
473
 
                                struct grub_nilfs2_btree_node *node,
474
 
                                int index)
475
 
{
476
 
  return
477
 
    grub_le_to_cpu64 (*(grub_nilfs2_btree_node_dptrs (data, node) + index));
478
 
}
479
 
 
480
 
static inline int
481
 
grub_nilfs2_btree_get_nonroot_node (struct grub_nilfs2_data *data,
482
 
                                    grub_uint64_t ptr, void *block)
483
 
{
484
 
  grub_disk_t disk = data->disk;
485
 
  unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
486
 
 
487
 
  return grub_disk_read (disk, ptr * nilfs2_block_count, 0,
488
 
                         NILFS2_BLOCK_SIZE (data), block);
489
 
}
490
 
 
491
 
static grub_uint64_t
492
 
grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
493
 
                          struct grub_nilfs2_inode *inode,
494
 
                          grub_uint64_t key, int need_translate)
495
 
{
496
 
  struct grub_nilfs2_btree_node *node;
497
 
  unsigned char block[NILFS2_BLOCK_SIZE (data)];
498
 
  grub_uint64_t ptr;
499
 
  int level, found, index;
500
 
 
501
 
  node = grub_nilfs2_btree_get_root (inode);
502
 
  level = grub_nilfs2_btree_get_level (node);
503
 
 
504
 
  found = grub_nilfs2_btree_node_lookup (node, key, &index);
505
 
  ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
506
 
  if (need_translate)
507
 
    ptr = grub_nilfs2_dat_translate (data, ptr);
508
 
 
509
 
  for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--)
510
 
    {
511
 
      grub_nilfs2_btree_get_nonroot_node (data, ptr, block);
512
 
      if (grub_errno)
513
 
        {
514
 
          return -1;
515
 
        }
516
 
      node = (struct grub_nilfs2_btree_node *) block;
517
 
 
518
 
      if (node->bn_level != level)
519
 
        {
520
 
          grub_error (GRUB_ERR_BAD_FS, "btree level mismatch\n");
521
 
          return -1;
522
 
        }
523
 
 
524
 
      if (!found)
525
 
        found = grub_nilfs2_btree_node_lookup (node, key, &index);
526
 
      else
527
 
        index = 0;
528
 
 
529
 
      if (index < grub_nilfs2_btree_node_nchildren_max (data, node))
530
 
        {
531
 
          ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
532
 
          if (need_translate)
533
 
            ptr = grub_nilfs2_dat_translate (data, ptr);
534
 
        }
535
 
      else
536
 
        {
537
 
          grub_error (GRUB_ERR_BAD_FS, "btree corruption\n");
538
 
          return -1;
539
 
        }
540
 
    }
541
 
 
542
 
  if (!found)
543
 
    return -1;
544
 
 
545
 
  return ptr;
546
 
}
547
 
 
548
 
static inline grub_uint64_t
549
 
grub_nilfs2_direct_lookup (struct grub_nilfs2_inode *inode, grub_uint64_t key)
550
 
{
551
 
  return grub_le_to_cpu64 (inode->i_bmap[1 + key]);
552
 
}
553
 
 
554
 
static inline grub_uint64_t
555
 
grub_nilfs2_bmap_lookup (struct grub_nilfs2_data *data,
556
 
                         struct grub_nilfs2_inode *inode,
557
 
                         grub_uint64_t key, int need_translate)
558
 
{
559
 
  struct grub_nilfs2_btree_node *root = grub_nilfs2_btree_get_root (inode);
560
 
  if (root->bn_flags & NILFS_BMAP_LARGE)
561
 
    return grub_nilfs2_btree_lookup (data, inode, key, need_translate);
562
 
  else
563
 
    {
564
 
      grub_uint64_t ptr;
565
 
      ptr = grub_nilfs2_direct_lookup (inode, key);
566
 
      if (need_translate)
567
 
        ptr = grub_nilfs2_dat_translate (data, ptr);
568
 
      return ptr;
569
 
    }
570
 
}
571
 
 
572
 
static grub_uint64_t
573
 
grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key)
574
 
{
575
 
  struct grub_nilfs2_dat_entry entry;
576
 
  grub_disk_t disk = data->disk;
577
 
  grub_uint64_t pptr;
578
 
  grub_uint32_t blockno, offset;
579
 
  unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
580
 
 
581
 
  blockno = grub_nilfs2_palloc_entry_offset (data, key,
582
 
                                             sizeof (struct
583
 
                                                     grub_nilfs2_dat_entry));
584
 
 
585
 
  grub_divmod64 (key * sizeof (struct grub_nilfs2_dat_entry),
586
 
                 NILFS2_BLOCK_SIZE (data), &offset);
587
 
 
588
 
  pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_dat, blockno, 0);
589
 
  if (pptr == (grub_uint64_t) - 1)
590
 
    {
591
 
      grub_error (GRUB_ERR_BAD_FS, "btree lookup failure");
592
 
      return -1;
593
 
    }
594
 
 
595
 
  grub_disk_read (disk, pptr * nilfs2_block_count, offset,
596
 
                  sizeof (struct grub_nilfs2_dat_entry), &entry);
597
 
 
598
 
  return grub_le_to_cpu64 (entry.de_blocknr);
599
 
}
600
 
 
601
 
 
602
 
static grub_disk_addr_t
603
 
grub_nilfs2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
604
 
{
605
 
  struct grub_nilfs2_data *data = node->data;
606
 
  struct grub_nilfs2_inode *inode = &node->inode;
607
 
  grub_uint64_t pptr = -1;
608
 
 
609
 
  pptr = grub_nilfs2_bmap_lookup (data, inode, fileblock, 1);
610
 
  if (pptr == (grub_uint64_t) - 1)
611
 
    {
612
 
      grub_error (GRUB_ERR_BAD_FS, "btree lookup failure");
613
 
      return -1;
614
 
    }
615
 
 
616
 
  return pptr;
617
 
}
618
 
 
619
 
/* Read LEN bytes from the file described by DATA starting with byte
620
 
   POS.  Return the amount of read bytes in READ.  */
621
 
static grub_ssize_t
622
 
grub_nilfs2_read_file (grub_fshelp_node_t node,
623
 
                       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
624
 
                                                           sector,
625
 
                                                           unsigned offset,
626
 
                                                           unsigned length),
627
 
                       int pos, grub_size_t len, char *buf)
628
 
{
629
 
  return grub_fshelp_read_file (node->data->disk, node, read_hook,
630
 
                                pos, len, buf, grub_nilfs2_read_block,
631
 
                                grub_le_to_cpu64 (node->inode.i_size),
632
 
                                LOG2_NILFS2_BLOCK_SIZE (node->data));
633
 
 
634
 
}
635
 
 
636
 
static grub_err_t
637
 
grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data,
638
 
                             grub_uint64_t cpno,
639
 
                             struct grub_nilfs2_checkpoint *cpp)
640
 
{
641
 
  grub_uint64_t blockno;
642
 
  grub_uint32_t offset;
643
 
  grub_uint64_t pptr;
644
 
  grub_disk_t disk = data->disk;
645
 
  unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
646
 
 
647
 
  /* Assume sizeof(struct grub_nilfs2_cpfile_header) < 
648
 
     sizeof(struct grub_nilfs2_checkpoint).
649
 
   */
650
 
  blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) /
651
 
                           sizeof (struct grub_nilfs2_checkpoint), &offset);
652
 
 
653
 
  pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1);
654
 
  if (pptr == (grub_uint64_t) - 1)
655
 
    {
656
 
      return grub_error (GRUB_ERR_BAD_FS, "btree lookup failure");
657
 
    }
658
 
 
659
 
  return grub_disk_read (disk, pptr * nilfs2_block_count,
660
 
                         offset * sizeof (struct grub_nilfs2_checkpoint),
661
 
                         sizeof (struct grub_nilfs2_checkpoint), cpp);
662
 
}
663
 
 
664
 
static inline grub_err_t
665
 
grub_nilfs2_read_last_checkpoint (struct grub_nilfs2_data *data,
666
 
                                  struct grub_nilfs2_checkpoint *cpp)
667
 
{
668
 
  return grub_nilfs2_read_checkpoint (data,
669
 
                                      grub_le_to_cpu64 (data->
670
 
                                                        sblock.s_last_cno),
671
 
                                      cpp);
672
 
}
673
 
 
674
 
/* Read the inode INO for the file described by DATA into INODE.  */
675
 
static grub_err_t
676
 
grub_nilfs2_read_inode (struct grub_nilfs2_data *data,
677
 
                        grub_uint64_t ino, struct grub_nilfs2_inode *inodep)
678
 
{
679
 
  grub_uint64_t blockno;
680
 
  unsigned int offset;
681
 
  grub_uint64_t pptr;
682
 
  grub_disk_t disk = data->disk;
683
 
  unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
684
 
 
685
 
  blockno = grub_nilfs2_palloc_entry_offset (data, ino,
686
 
                                             sizeof (struct
687
 
                                                     grub_nilfs2_inode));
688
 
 
689
 
  grub_divmod64 (sizeof (struct grub_nilfs2_inode) * ino,
690
 
                 NILFS2_BLOCK_SIZE (data), &offset);
691
 
  pptr = grub_nilfs2_bmap_lookup (data, &data->ifile, blockno, 1);
692
 
  if (pptr == (grub_uint64_t) - 1)
693
 
    {
694
 
      return grub_error (GRUB_ERR_BAD_FS, "btree lookup failure");
695
 
    }
696
 
 
697
 
  return grub_disk_read (disk, pptr * nilfs2_block_count, offset,
698
 
                         sizeof (struct grub_nilfs2_inode), inodep);
699
 
}
700
 
 
701
 
static int
702
 
grub_nilfs2_valid_sb (struct grub_nilfs2_super_block *sbp)
703
 
{
704
 
  if (grub_le_to_cpu16 (sbp->s_magic) != NILFS2_SUPER_MAGIC)
705
 
    return 0;
706
 
 
707
 
  if (grub_le_to_cpu32 (sbp->s_rev_level) != NILFS_SUPORT_REV)
708
 
    return 0;
709
 
 
710
 
  return 1;
711
 
}
712
 
 
713
 
static grub_err_t
714
 
grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
715
 
{
716
 
  grub_disk_t disk = data->disk;
717
 
  struct grub_nilfs2_super_block sb2;
718
 
  grub_uint64_t partition_size;
719
 
  int valid[2];
720
 
  int swp = 0;
721
 
 
722
 
  /* Read first super block. */
723
 
  grub_disk_read (disk, NILFS_1ST_SUPER_BLOCK, 0,
724
 
                  sizeof (struct grub_nilfs2_super_block), &data->sblock);
725
 
  /* Make sure if 1st super block is valid.  */
726
 
  valid[0] = grub_nilfs2_valid_sb (&data->sblock);
727
 
 
728
 
  partition_size = grub_disk_get_size (disk);
729
 
  if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
730
 
    {
731
 
      /* Read second super block. */
732
 
      grub_disk_read (disk, NILFS_2ND_SUPER_BLOCK (partition_size), 0,
733
 
                      sizeof (struct grub_nilfs2_super_block), &sb2);
734
 
      /* Make sure if 2nd super block is valid.  */
735
 
      valid[1] = grub_nilfs2_valid_sb (&sb2);
736
 
    }
737
 
  else
738
 
    /* 2nd super block may not exist, so it's invalid. */
739
 
    valid[1] = 0;
740
 
 
741
 
 
742
 
 
743
 
  if (!valid[0] && !valid[1])
744
 
    return grub_error (GRUB_ERR_BAD_FS, "not a nilfs2 filesystem");
745
 
 
746
 
  swp = valid[1] && (!valid[0] ||
747
 
                     grub_le_to_cpu64 (data->sblock.s_last_cno) <
748
 
                     grub_le_to_cpu64 (sb2.s_last_cno));
749
 
 
750
 
  /* swap if first super block is invalid or older than second one. */
751
 
  if (swp)
752
 
    grub_memcpy (&data->sblock, &sb2,
753
 
                 sizeof (struct grub_nilfs2_super_block));
754
 
 
755
 
  grub_errno = GRUB_ERR_NONE;
756
 
  return grub_errno;
757
 
}
758
 
 
759
 
static struct grub_nilfs2_data *
760
 
grub_nilfs2_mount (grub_disk_t disk)
761
 
{
762
 
  struct grub_nilfs2_data *data;
763
 
  struct grub_nilfs2_segment_summary ss;
764
 
  struct grub_nilfs2_checkpoint last_checkpoint;
765
 
  grub_uint64_t last_pseg;
766
 
  grub_uint32_t nblocks;
767
 
  unsigned int nilfs2_block_count;
768
 
 
769
 
  data = grub_malloc (sizeof (struct grub_nilfs2_data));
770
 
  if (!data)
771
 
    return 0;
772
 
 
773
 
  data->disk = disk;
774
 
 
775
 
  /* Read the superblock.  */
776
 
  grub_nilfs2_load_sb (data);
777
 
  if (grub_errno)
778
 
    goto fail;
779
 
 
780
 
  nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
781
 
 
782
 
  /* Read the last segment summary. */
783
 
  last_pseg = grub_le_to_cpu64 (data->sblock.s_last_pseg);
784
 
  grub_disk_read (disk, last_pseg * nilfs2_block_count, 0,
785
 
                  sizeof (struct grub_nilfs2_segment_summary), &ss);
786
 
 
787
 
  if (grub_errno)
788
 
    goto fail;
789
 
 
790
 
  /* Read the super root block. */
791
 
  nblocks = grub_le_to_cpu32 (ss.ss_nblocks);
792
 
  grub_disk_read (disk, (last_pseg + (nblocks - 1)) * nilfs2_block_count, 0,
793
 
                  sizeof (struct grub_nilfs2_super_root), &data->sroot);
794
 
 
795
 
  if (grub_errno)
796
 
    goto fail;
797
 
 
798
 
  grub_nilfs2_read_last_checkpoint (data, &last_checkpoint);
799
 
 
800
 
  if (grub_errno)
801
 
    goto fail;
802
 
 
803
 
  grub_memcpy (&data->ifile, &last_checkpoint.cp_ifile_inode,
804
 
               sizeof (struct grub_nilfs2_inode));
805
 
 
806
 
  data->diropen.data = data;
807
 
  data->diropen.ino = 2;
808
 
  data->diropen.inode_read = 1;
809
 
  data->inode = &data->diropen.inode;
810
 
 
811
 
  grub_nilfs2_read_inode (data, 2, data->inode);
812
 
 
813
 
  return data;
814
 
 
815
 
fail:
816
 
  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
817
 
    grub_error (GRUB_ERR_BAD_FS, "not a nilfs2 filesystem");
818
 
 
819
 
  grub_free (data);
820
 
  return 0;
821
 
}
822
 
 
823
 
static char *
824
 
grub_nilfs2_read_symlink (grub_fshelp_node_t node)
825
 
{
826
 
  char *symlink;
827
 
  struct grub_fshelp_node *diro = node;
828
 
 
829
 
  if (!diro->inode_read)
830
 
    {
831
 
      grub_nilfs2_read_inode (diro->data, diro->ino, &diro->inode);
832
 
      if (grub_errno)
833
 
        return 0;
834
 
    }
835
 
 
836
 
  symlink = grub_malloc (grub_le_to_cpu64 (diro->inode.i_size) + 1);
837
 
  if (!symlink)
838
 
    return 0;
839
 
 
840
 
  grub_nilfs2_read_file (diro, 0, 0,
841
 
                         grub_le_to_cpu64 (diro->inode.i_size), symlink);
842
 
  if (grub_errno)
843
 
    {
844
 
      grub_free (symlink);
845
 
      return 0;
846
 
    }
847
 
 
848
 
  symlink[grub_le_to_cpu64 (diro->inode.i_size)] = '\0';
849
 
  return symlink;
850
 
}
851
 
 
852
 
static int
853
 
grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
854
 
                         int NESTED_FUNC_ATTR
855
 
                         (*hook) (const char *filename,
856
 
                                  enum grub_fshelp_filetype filetype,
857
 
                                  grub_fshelp_node_t node))
858
 
{
859
 
  unsigned int fpos = 0;
860
 
  struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
861
 
 
862
 
  if (!diro->inode_read)
863
 
    {
864
 
      grub_nilfs2_read_inode (diro->data, diro->ino, &diro->inode);
865
 
      if (grub_errno)
866
 
        return 0;
867
 
    }
868
 
 
869
 
  /* Iterate files.  */
870
 
  while (fpos < grub_le_to_cpu64 (diro->inode.i_size))
871
 
    {
872
 
      struct grub_nilfs2_dir_entry dirent;
873
 
 
874
 
      grub_nilfs2_read_file (diro, 0, fpos,
875
 
                             sizeof (struct grub_nilfs2_dir_entry),
876
 
                             (char *) &dirent);
877
 
      if (grub_errno)
878
 
        return 0;
879
 
 
880
 
      if (dirent.rec_len == 0)
881
 
        return 0;
882
 
 
883
 
      if (dirent.name_len != 0)
884
 
        {
885
 
          char filename[dirent.name_len + 1];
886
 
          struct grub_fshelp_node *fdiro;
887
 
          enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
888
 
 
889
 
          grub_nilfs2_read_file (diro, 0,
890
 
                                 fpos + sizeof (struct grub_nilfs2_dir_entry),
891
 
                                 dirent.name_len, filename);
892
 
          if (grub_errno)
893
 
            return 0;
894
 
 
895
 
          fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
896
 
          if (!fdiro)
897
 
            return 0;
898
 
 
899
 
          fdiro->data = diro->data;
900
 
          fdiro->ino = grub_le_to_cpu64 (dirent.inode);
901
 
 
902
 
          filename[dirent.name_len] = '\0';
903
 
 
904
 
          if (dirent.file_type != NILFS_FT_UNKNOWN)
905
 
            {
906
 
              fdiro->inode_read = 0;
907
 
 
908
 
              if (dirent.file_type == NILFS_FT_DIR)
909
 
                type = GRUB_FSHELP_DIR;
910
 
              else if (dirent.file_type == NILFS_FT_SYMLINK)
911
 
                type = GRUB_FSHELP_SYMLINK;
912
 
              else if (dirent.file_type == NILFS_FT_REG_FILE)
913
 
                type = GRUB_FSHELP_REG;
914
 
            }
915
 
          else
916
 
            {
917
 
              /* The filetype can not be read from the dirent, read
918
 
                 the inode to get more information.  */
919
 
              grub_nilfs2_read_inode (diro->data,
920
 
                                      grub_le_to_cpu64 (dirent.inode),
921
 
                                      &fdiro->inode);
922
 
              if (grub_errno)
923
 
                {
924
 
                  grub_free (fdiro);
925
 
                  return 0;
926
 
                }
927
 
 
928
 
              fdiro->inode_read = 1;
929
 
 
930
 
              if ((grub_le_to_cpu16 (fdiro->inode.i_mode)
931
 
                   & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
932
 
                type = GRUB_FSHELP_DIR;
933
 
              else if ((grub_le_to_cpu16 (fdiro->inode.i_mode)
934
 
                        & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
935
 
                type = GRUB_FSHELP_SYMLINK;
936
 
              else if ((grub_le_to_cpu16 (fdiro->inode.i_mode)
937
 
                        & FILETYPE_INO_MASK) == FILETYPE_INO_REG)
938
 
                type = GRUB_FSHELP_REG;
939
 
            }
940
 
 
941
 
          if (hook (filename, type, fdiro))
942
 
            return 1;
943
 
        }
944
 
 
945
 
      fpos += grub_le_to_cpu16 (dirent.rec_len);
946
 
    }
947
 
 
948
 
  return 0;
949
 
}
950
 
 
951
 
/* Open a file named NAME and initialize FILE.  */
952
 
static grub_err_t
953
 
grub_nilfs2_open (struct grub_file *file, const char *name)
954
 
{
955
 
  struct grub_nilfs2_data *data = NULL;
956
 
  struct grub_fshelp_node *fdiro = 0;
957
 
 
958
 
  grub_dl_ref (my_mod);
959
 
 
960
 
  data = grub_nilfs2_mount (file->device->disk);
961
 
  if (!data)
962
 
    goto fail;
963
 
 
964
 
  grub_fshelp_find_file (name, &data->diropen, &fdiro,
965
 
                         grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink,
966
 
                         GRUB_FSHELP_REG);
967
 
  if (grub_errno)
968
 
    goto fail;
969
 
 
970
 
  if (!fdiro->inode_read)
971
 
    {
972
 
      grub_nilfs2_read_inode (data, fdiro->ino, &fdiro->inode);
973
 
      if (grub_errno)
974
 
        goto fail;
975
 
    }
976
 
 
977
 
  grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_nilfs2_inode));
978
 
  grub_free (fdiro);
979
 
 
980
 
  file->size = grub_le_to_cpu64 (data->inode->i_size);
981
 
  file->data = data;
982
 
  file->offset = 0;
983
 
 
984
 
  return 0;
985
 
 
986
 
fail:
987
 
  if (fdiro != &data->diropen)
988
 
    grub_free (fdiro);
989
 
  grub_free (data);
990
 
 
991
 
  grub_dl_unref (my_mod);
992
 
 
993
 
  return grub_errno;
994
 
}
995
 
 
996
 
static grub_err_t
997
 
grub_nilfs2_close (grub_file_t file)
998
 
{
999
 
  grub_free (file->data);
1000
 
 
1001
 
  grub_dl_unref (my_mod);
1002
 
 
1003
 
  return GRUB_ERR_NONE;
1004
 
}
1005
 
 
1006
 
/* Read LEN bytes data from FILE into BUF.  */
1007
 
static grub_ssize_t
1008
 
grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len)
1009
 
{
1010
 
  struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data;
1011
 
 
1012
 
  return grub_nilfs2_read_file (&data->diropen, file->read_hook,
1013
 
                                file->offset, len, buf);
1014
 
}
1015
 
 
1016
 
static grub_err_t
1017
 
grub_nilfs2_dir (grub_device_t device, const char *path,
1018
 
                 int (*hook) (const char *filename,
1019
 
                              const struct grub_dirhook_info * info))
1020
 
{
1021
 
  struct grub_nilfs2_data *data = 0;
1022
 
  struct grub_fshelp_node *fdiro = 0;
1023
 
 
1024
 
  auto int NESTED_FUNC_ATTR iterate (const char *filename,
1025
 
                                     enum grub_fshelp_filetype filetype,
1026
 
                                     grub_fshelp_node_t node);
1027
 
 
1028
 
  int NESTED_FUNC_ATTR iterate (const char *filename,
1029
 
                                enum grub_fshelp_filetype filetype,
1030
 
                                grub_fshelp_node_t node)
1031
 
  {
1032
 
    struct grub_dirhook_info info;
1033
 
    grub_memset (&info, 0, sizeof (info));
1034
 
    if (!node->inode_read)
1035
 
      {
1036
 
        grub_nilfs2_read_inode (data, node->ino, &node->inode);
1037
 
        if (!grub_errno)
1038
 
          node->inode_read = 1;
1039
 
        grub_errno = GRUB_ERR_NONE;
1040
 
      }
1041
 
    if (node->inode_read)
1042
 
      {
1043
 
        info.mtimeset = 1;
1044
 
        info.mtime = grub_le_to_cpu64 (node->inode.i_mtime);
1045
 
      }
1046
 
 
1047
 
    info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
1048
 
    grub_free (node);
1049
 
    return hook (filename, &info);
1050
 
  }
1051
 
 
1052
 
  grub_dl_ref (my_mod);
1053
 
 
1054
 
  data = grub_nilfs2_mount (device->disk);
1055
 
  if (!data)
1056
 
    goto fail;
1057
 
 
1058
 
  grub_fshelp_find_file (path, &data->diropen, &fdiro,
1059
 
                         grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink,
1060
 
                         GRUB_FSHELP_DIR);
1061
 
  if (grub_errno)
1062
 
    goto fail;
1063
 
 
1064
 
  grub_nilfs2_iterate_dir (fdiro, iterate);
1065
 
 
1066
 
fail:
1067
 
  if (fdiro != &data->diropen)
1068
 
    grub_free (fdiro);
1069
 
  grub_free (data);
1070
 
 
1071
 
  grub_dl_unref (my_mod);
1072
 
 
1073
 
  return grub_errno;
1074
 
}
1075
 
 
1076
 
static grub_err_t
1077
 
grub_nilfs2_label (grub_device_t device, char **label)
1078
 
{
1079
 
  struct grub_nilfs2_data *data;
1080
 
  grub_disk_t disk = device->disk;
1081
 
 
1082
 
  grub_dl_ref (my_mod);
1083
 
 
1084
 
  data = grub_nilfs2_mount (disk);
1085
 
  if (data)
1086
 
    *label = grub_strndup (data->sblock.s_volume_name, 14);
1087
 
  else
1088
 
    *label = NULL;
1089
 
 
1090
 
  grub_dl_unref (my_mod);
1091
 
 
1092
 
  grub_free (data);
1093
 
 
1094
 
  return grub_errno;
1095
 
}
1096
 
 
1097
 
static grub_err_t
1098
 
grub_nilfs2_uuid (grub_device_t device, char **uuid)
1099
 
{
1100
 
  struct grub_nilfs2_data *data;
1101
 
  grub_disk_t disk = device->disk;
1102
 
 
1103
 
  grub_dl_ref (my_mod);
1104
 
 
1105
 
  data = grub_nilfs2_mount (disk);
1106
 
  if (data)
1107
 
    {
1108
 
      *uuid =
1109
 
        grub_xasprintf
1110
 
        ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%0x-%02x%02x%02x%02x%02x%02x",
1111
 
         data->sblock.s_uuid[0], data->sblock.s_uuid[1],
1112
 
         data->sblock.s_uuid[2], data->sblock.s_uuid[3],
1113
 
         data->sblock.s_uuid[4], data->sblock.s_uuid[5],
1114
 
         data->sblock.s_uuid[6], data->sblock.s_uuid[7],
1115
 
         data->sblock.s_uuid[8], data->sblock.s_uuid[9],
1116
 
         data->sblock.s_uuid[10], data->sblock.s_uuid[11],
1117
 
         data->sblock.s_uuid[12], data->sblock.s_uuid[13],
1118
 
         data->sblock.s_uuid[14], data->sblock.s_uuid[15]);
1119
 
    }
1120
 
  else
1121
 
    *uuid = NULL;
1122
 
 
1123
 
  grub_dl_unref (my_mod);
1124
 
 
1125
 
  grub_free (data);
1126
 
 
1127
 
  return grub_errno;
1128
 
}
1129
 
 
1130
 
/* Get mtime.  */
1131
 
static grub_err_t
1132
 
grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm)
1133
 
{
1134
 
  struct grub_nilfs2_data *data;
1135
 
  grub_disk_t disk = device->disk;
1136
 
 
1137
 
  grub_dl_ref (my_mod);
1138
 
 
1139
 
  data = grub_nilfs2_mount (disk);
1140
 
  if (!data)
1141
 
    *tm = 0;
1142
 
  else
1143
 
    *tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_mtime);
1144
 
 
1145
 
  grub_dl_unref (my_mod);
1146
 
 
1147
 
  grub_free (data);
1148
 
 
1149
 
  return grub_errno;
1150
 
}
1151
 
 
1152
 
 
1153
 
 
1154
 
static struct grub_fs grub_nilfs2_fs = {
1155
 
  .name = "nilfs2",
1156
 
  .dir = grub_nilfs2_dir,
1157
 
  .open = grub_nilfs2_open,
1158
 
  .read = grub_nilfs2_read,
1159
 
  .close = grub_nilfs2_close,
1160
 
  .label = grub_nilfs2_label,
1161
 
  .uuid = grub_nilfs2_uuid,
1162
 
  .mtime = grub_nilfs2_mtime,
1163
 
#ifdef GRUB_UTIL
1164
 
  .reserved_first_sector = 1,
1165
 
#endif
1166
 
  .next = 0
1167
 
};
1168
 
 
1169
 
GRUB_MOD_INIT (nilfs2)
1170
 
{
1171
 
  grub_fs_register (&grub_nilfs2_fs);
1172
 
  my_mod = mod;
1173
 
}
1174
 
 
1175
 
GRUB_MOD_FINI (nilfs2)
1176
 
{
1177
 
  grub_fs_unregister (&grub_nilfs2_fs);
1178
 
}