/*
* nilfs2.c - New Implementation of Log filesystem
*
* Written by Jiro SEKIBA <jir@unicus.jp>
*
* Copyright (C) 2003,2004,2005,2007,2008,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/* Filetype information as used in inodes. */
GRUB_MOD_LICENSE ("GPLv3+");
/* Magic value used to identify an nilfs2 filesystem. */
/* nilfs btree node flag. */
/* nilfs btree node level. */
#define NILFS_BTREE_LEVEL_DATA 0
/* nilfs 1st super block posission from beginning of the partition
in 512 block size */
/* nilfs 2nd super block posission from beginning of the partition
in 512 block size */
struct grub_nilfs2_inode
{
};
struct grub_nilfs2_super_root
{
};
struct grub_nilfs2_super_block
{
};
struct grub_nilfs2_dir_entry
{
#if 0 /* followed by file name. */
char name[NILFS_NAME_LEN];
char pad;
#endif
} __attribute__ ((packed));
enum
{
};
struct grub_nilfs2_finfo
{
};
struct grub_nilfs2_binfo_v
{
};
struct grub_nilfs2_binfo_dat
{
};
union grub_nilfs2_binfo
{
};
struct grub_nilfs2_segment_summary
{
};
struct grub_nilfs2_btree_node
{
};
{
};
struct grub_nilfs2_dat_entry
{
};
struct grub_nilfs2_snapshot_list
{
};
struct grub_nilfs2_cpfile_header
{
};
struct grub_nilfs2_checkpoint
{
};
/* nilfs extra padding for nonroot btree node. */
#define NILFS_BTREE_ROOT_NCHILDREN_MAX \
((NILFS_BTREE_ROOT_SIZE - sizeof(struct nilfs_btree_node)) / \
(sizeof(grub_uint64_t) + sizeof(grub_uint64_t)) )
struct grub_fshelp_node
{
int inode_read;
};
struct grub_nilfs2_data
{
};
/* Log2 size of nilfs2 block in 512 blocks. */
/* Log2 size of nilfs2 block in bytes. */
/* The size of an nilfs2 block in bytes. */
static grub_uint64_t
static inline unsigned long
{
}
static inline grub_uint64_t
{
}
static inline grub_uint32_t
{
return NILFS2_BLOCK_SIZE (data) /
sizeof (struct grub_nilfs2_palloc_group_desc);
}
static inline grub_uint32_t
unsigned long log_entry_size)
{
}
static inline grub_uint32_t
unsigned long log_entry_size)
{
log_entry_size))) + 1;
}
static inline grub_uint32_t
unsigned long log_entry_size)
{
return grub_nilfs2_palloc_groups_per_desc_block (data) *
}
static inline grub_uint32_t
unsigned long group,
unsigned long log_entry_size)
{
}
static inline grub_uint32_t
unsigned long group,
unsigned long log_entry_size)
{
+ 1
}
static inline grub_uint32_t
unsigned long log_entry_size)
{
unsigned long group;
}
static inline struct grub_nilfs2_btree_node *
{
}
static inline int
{
}
static inline grub_uint64_t *
{
0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE / sizeof (grub_uint64_t))));
}
static inline grub_uint64_t
int index)
{
}
static inline int
{
low = 0;
index = 0;
s = 0;
{
{
return 1;
}
{
s = -1;
}
else
{
s = 1;
}
}
{
if (s > 0 && index > 0)
index--;
}
else if (s < 0)
index++;
return s == 0;
}
static inline int
struct grub_nilfs2_btree_node *node)
{
sizeof (struct grub_nilfs2_btree_node) -
(sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
}
static inline grub_uint64_t *
struct grub_nilfs2_btree_node *node)
{
node));
}
static inline grub_uint64_t
struct grub_nilfs2_btree_node *node,
int index)
{
return
}
static inline int
{
}
static grub_uint64_t
struct grub_nilfs2_inode *inode,
{
if (need_translate)
{
if (grub_errno)
{
return -1;
}
{
return -1;
}
if (!found)
else
index = 0;
{
if (need_translate)
}
else
{
return -1;
}
}
if (!found)
return -1;
return ptr;
}
static inline grub_uint64_t
{
}
static inline grub_uint64_t
struct grub_nilfs2_inode *inode,
{
else
{
if (need_translate)
return ptr;
}
}
static grub_uint64_t
{
{
return -1;
}
sizeof (struct grub_nilfs2_dat_entry), &entry);
}
static grub_disk_addr_t
{
{
return -1;
}
return pptr;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
unsigned offset,
unsigned length),
{
}
static grub_err_t
struct grub_nilfs2_checkpoint *cpp)
{
/* Assume sizeof(struct grub_nilfs2_cpfile_header) <
sizeof(struct grub_nilfs2_checkpoint).
*/
sizeof (struct grub_nilfs2_checkpoint), &offset);
{
}
offset * sizeof (struct grub_nilfs2_checkpoint),
sizeof (struct grub_nilfs2_checkpoint), cpp);
}
static inline grub_err_t
struct grub_nilfs2_checkpoint *cpp)
{
return grub_nilfs2_read_checkpoint (data,
cpp);
}
/* Read the inode INO for the file described by DATA into INODE. */
static grub_err_t
{
{
}
sizeof (struct grub_nilfs2_inode), inodep);
}
static int
{
return 0;
return 0;
return 1;
}
static grub_err_t
{
int swp = 0;
/* Read first super block. */
if (err)
return err;
/* Make sure if 1st super block is valid. */
if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
{
/* Read second super block. */
sizeof (struct grub_nilfs2_super_block), &sb2);
if (err)
{
valid[1] = 0;
}
else
/* Make sure if 2nd super block is valid. */
}
else
/* 2nd super block may not exist, so it's invalid. */
valid[1] = 0;
/* swap if first super block is invalid or older than second one. */
if (swp)
sizeof (struct grub_nilfs2_super_block));
return GRUB_ERR_NONE;
}
static struct grub_nilfs2_data *
{
unsigned int nilfs2_block_count;
if (!data)
return 0;
/* Read the superblock. */
if (grub_errno)
goto fail;
/* Read the last segment summary. */
sizeof (struct grub_nilfs2_segment_summary), &ss);
if (grub_errno)
goto fail;
/* Read the super root block. */
if (grub_errno)
goto fail;
if (grub_errno)
goto fail;
sizeof (struct grub_nilfs2_inode));
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
return 0;
}
static char *
{
char *symlink;
if (!diro->inode_read)
{
if (grub_errno)
return 0;
}
if (!symlink)
return 0;
grub_nilfs2_read_file (diro, 0, 0,
if (grub_errno)
{
return 0;
}
return symlink;
}
static int
int NESTED_FUNC_ATTR
enum grub_fshelp_filetype filetype,
{
if (!diro->inode_read)
{
if (grub_errno)
return 0;
}
/* Iterate files. */
{
sizeof (struct grub_nilfs2_dir_entry),
(char *) &dirent);
if (grub_errno)
return 0;
return 0;
{
fpos + sizeof (struct grub_nilfs2_dir_entry),
if (grub_errno)
return 0;
if (!fdiro)
return 0;
{
fdiro->inode_read = 0;
}
else
{
/* The filetype can not be read from the dirent, read
the inode to get more information. */
if (grub_errno)
{
return 0;
}
}
return 1;
}
}
return 0;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
{
if (!data)
goto fail;
if (grub_errno)
goto fail;
if (!fdiro->inode_read)
{
if (grub_errno)
goto fail;
}
return 0;
fail:
return grub_errno;
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
{
}
static grub_err_t
const struct grub_dirhook_info * info))
{
enum grub_fshelp_filetype filetype,
enum grub_fshelp_filetype filetype,
{
if (!node->inode_read)
{
if (!grub_errno)
}
if (node->inode_read)
{
}
}
if (!data)
goto fail;
if (grub_errno)
goto fail;
fail:
return grub_errno;
}
static grub_err_t
{
if (data)
else
return grub_errno;
}
static grub_err_t
{
if (data)
{
*uuid =
("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
}
else
return grub_errno;
}
/* Get mtime. */
static grub_err_t
{
if (!data)
*tm = 0;
else
return grub_errno;
}
.name = "nilfs2",
.dir = grub_nilfs2_dir,
.open = grub_nilfs2_open,
.read = grub_nilfs2_read,
.uuid = grub_nilfs2_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
#endif
.next = 0
};
{
== sizeof (struct
== sizeof (struct grub_nilfs2_inode));
}
{
}