Am Freitag, den 15.05.2009, 18:40 +0900 schrieb Kouichi ONO:
> 
> grub-probe can't detect xfs with 512 byte i-node. 

Hello,

please try attached patch.
It would be good if you could try real grub too, if it can read files
correctly.

You can find intructions how to compile in the Debian wiki [0].
Even though it's german it should be unstandable. If not please ask.

[0]
http://wiki.debian.org/de/GRUB2/Anleitung/DebianPaketVonOriginalQuelltext

-- 
Felix Zielcke
Proud Debian Maintainer
diff --git a/fs/xfs.c b/fs/xfs.c
index ddaba57..d1bcd15 100644
--- a/fs/xfs.c
+++ b/fs/xfs.c
@@ -46,7 +46,8 @@ struct grub_xfs_sblock
   grub_uint8_t unused4[20];
   grub_uint8_t label[12];
   grub_uint8_t log2_bsize;
-  grub_uint8_t unused5[2];
+  grub_uint8_t log2_sect;
+  grub_uint8_t log2_inode;
   grub_uint8_t log2_inop;
   grub_uint8_t log2_agblk;
   grub_uint8_t unused6[67];
@@ -131,21 +132,19 @@ struct grub_xfs_dirblock_tail
 struct grub_fshelp_node
 {
   struct grub_xfs_data *data;
-  struct grub_xfs_inode inode;
   grub_uint64_t ino;
   int inode_read;
+  struct grub_xfs_inode inode;
 };
 
 struct grub_xfs_data
 {
   struct grub_xfs_sblock sblock;
-  struct grub_xfs_inode *inode;
   grub_disk_t disk;
   int pos;
   int bsize;
   int agsize;
   struct grub_fshelp_node diropen;
-
 };
 
 static grub_dl_t my_mod;
@@ -194,7 +193,7 @@ grub_xfs_inode_block (struct grub_xfs_data *data,
   long long ag = GRUB_XFS_INO_AG (data, ino);
   long long block;
 
-  block = (inoinag >> 4) + ag * data->agsize;
+  block = (inoinag >> data->sblock.log2_inop) + ag * data->agsize;
   block <<= (data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS);
   return block;
 }
@@ -205,7 +204,8 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
 		       grub_uint64_t ino)
 {
   int inoag = GRUB_XFS_INO_INOINAG (data, ino);
-  return (inoag & ((1 << 4) - 1)) << 8;
+  return ((inoag & ((1 << data->sblock.log2_inop) - 1)) <<
+	  data->sblock.log2_inode);
 }
 
 
@@ -218,7 +218,7 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
 
   /* Read the inode.  */
   if (grub_disk_read (data->disk, block, offset,
-		      sizeof (struct grub_xfs_inode), inode))
+		      1 << data->sblock.log2_inode, inode))
     return grub_errno;
 
   if (grub_strncmp ((char *) inode->magic, "IN", 2))
@@ -264,7 +264,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
             }
 
           if (grub_disk_read (node->data->disk,
-                              grub_be_to_cpu64 (keys[i - 1 + XFS_INODE_EXTENTS])
+                              grub_be_to_cpu64 (keys[i - 1 + nrec])
                               << (node->data->sblock.log2_bsize
                                   - GRUB_DISK_SECTOR_BITS),
                               0, node->data->sblock.bsize, leaf))
@@ -400,7 +400,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
     {
       struct grub_fshelp_node *fdiro;
 
-      fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+      fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
+			   - sizeof (struct grub_xfs_inode)
+			   + (1 << diro->data->sblock.log2_inode));
       if (!fdiro)
 	return 0;
 
@@ -420,8 +422,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
     {
     case XFS_INODE_FORMAT_INO:
       {
-	struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
-	int smallino = !diro->inode.data.dir.dirhead.smallino;
+	struct grub_xfs_dir_entry *de =
+	  &diro->inode.data.dir.direntry[0];
+	int smallino =
+	  !diro->inode.data.dir.dirhead.smallino;
 	int i;
 	grub_uint64_t parent;
 
@@ -429,7 +433,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
 	   parent inode number is small too.  */
 	if (smallino)
 	  {
-	    parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
+	    parent =
+	      grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
 	    parent = grub_cpu_to_be64 (parent);
 	    /* The header is a bit smaller than usual.  */
 	    de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
@@ -577,7 +582,7 @@ grub_xfs_mount (grub_disk_t disk)
 {
   struct grub_xfs_data *data = 0;
 
-  data = grub_malloc (sizeof (struct grub_xfs_data));
+  data = grub_zalloc (sizeof (struct grub_xfs_data));
   if (!data)
     return 0;
 
@@ -592,6 +597,14 @@ grub_xfs_mount (grub_disk_t disk)
       goto fail;
     }
 
+  data = grub_realloc (data,
+		       sizeof (struct grub_xfs_data)
+		       - sizeof (struct grub_xfs_inode)
+		       + (1 << data->sblock.log2_inode));
+
+  if (! data)
+    goto fail;
+
   data->diropen.data = data;
   data->diropen.ino = data->sblock.rootino;
   data->diropen.inode_read = 1;
@@ -599,10 +612,9 @@ grub_xfs_mount (grub_disk_t disk)
   data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
 
   data->disk = disk;
-  data->inode = &data->diropen.inode;
   data->pos = 0;
 
-  grub_xfs_read_inode (data, data->diropen.ino, data->inode);
+  grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode);
 
   return data;
  fail:
@@ -643,7 +655,7 @@ grub_xfs_dir (grub_device_t device, const char *path,
 
   data = grub_xfs_mount (device->disk);
   if (!data)
-    goto fail;
+    goto mount_fail;
 
   grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_xfs_iterate_dir,
 			 grub_xfs_read_symlink, GRUB_FSHELP_DIR);
@@ -657,11 +669,11 @@ grub_xfs_dir (grub_device_t device, const char *path,
     grub_free (fdiro);
   grub_free (data);
 
+ mount_fail:
+
   grub_dl_unref (my_mod);
 
   return grub_errno;
-
-  return 0;
 }
 
 
@@ -676,7 +688,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
 
   data = grub_xfs_mount (file->device->disk);
   if (!data)
-    goto fail;
+    goto mount_fail;
 
   grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_xfs_iterate_dir,
 			 grub_xfs_read_symlink, GRUB_FSHELP_REG);
@@ -690,12 +702,13 @@ grub_xfs_open (struct grub_file *file, const char *name)
 	goto fail;
     }
 
-  grub_memcpy (data->inode,
-	       &fdiro->inode,
-	       sizeof (struct grub_xfs_inode));
-  grub_free (fdiro);
+  if (fdiro != &data->diropen)
+    grub_memcpy (&data->diropen, fdiro,
+		 sizeof (struct grub_fshelp_node)
+		 - sizeof (struct grub_xfs_inode)
+		 + (1 << data->sblock.log2_inode));
 
-  file->size = grub_be_to_cpu64 (data->inode->size);
+  file->size = grub_be_to_cpu64 (data->diropen.inode.size);
   file->data = data;
   file->offset = 0;
 
@@ -706,6 +719,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
     grub_free (fdiro);
   grub_free (data);
 
+ mount_fail:
   grub_dl_unref (my_mod);
 
   return grub_errno;

Reply via email to