Whamcloud - gitweb
e2fsck: Support long symlinks which use extents
authorTheodore Ts'o <tytso@mit.edu>
Fri, 14 Mar 2008 03:05:00 +0000 (23:05 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 14 Mar 2008 03:05:00 +0000 (23:05 -0400)
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/pass2.c

index be6efe1..21208e0 100644 (file)
@@ -429,7 +429,7 @@ extern void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags,
 extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
 extern int e2fsck_pass1_check_device_inode(ext2_filsys fs,
                                           struct ext2_inode *inode);
-extern int e2fsck_pass1_check_symlink(ext2_filsys fs,
+extern int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
                                      struct ext2_inode *inode, char *buf);
 extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
                               struct ext2_inode *inode, int restart_flag,
index c598205..8638989 100644 (file)
@@ -163,17 +163,42 @@ int e2fsck_pass1_check_device_inode(ext2_filsys fs EXT2FS_ATTR((unused)),
  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
  * checks out, 0 if not.
  */
-int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode,
-                              char *buf)
+int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
+                              struct ext2_inode *inode, char *buf)
 {
        unsigned int len;
        int i;
        blk_t   blocks;
+       ext2_extent_handle_t    handle;
+       struct ext2_extent_info info;
+       struct ext2fs_extent    extent;
 
        if ((inode->i_size_high || inode->i_size == 0) ||
            (inode->i_flags & EXT2_INDEX_FL))
                return 0;
 
+       if (inode->i_flags & EXT4_EXTENTS_FL) {
+               if (inode->i_size > fs->blocksize)
+                       return 0;
+               if (ext2fs_extent_open(fs, ino, &handle))
+                       return 0;
+               i = 0;
+               if (ext2fs_extent_get_info(handle, &info) ||
+                   (info.num_entries != 1) ||
+                   (info.max_depth != 0))
+                       goto exit_extent;
+               if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent) ||
+                   (extent.e_lblk != 0) ||
+                   (extent.e_len != 1) ||
+                   (extent.e_pblk < fs->super->s_first_data_block) ||
+                   (extent.e_pblk >= fs->super->s_blocks_count))
+                       goto exit_extent;
+               i = 1;
+       exit_extent:
+               ext2fs_extent_free(handle);
+               return i;
+       }
+
        blocks = ext2fs_inode_data_blocks(fs, inode);
        if (blocks) {
                if ((inode->i_size >= fs->blocksize) ||
@@ -910,7 +935,8 @@ void e2fsck_pass1(e2fsck_t ctx)
                        check_size(ctx, &pctx);
                        ctx->fs_blockdev_count++;
                } else if (LINUX_S_ISLNK (inode->i_mode) &&
-                          e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
+                          e2fsck_pass1_check_symlink(fs, ino, inode, 
+                                                     block_buf)) {
                        check_immutable(ctx, &pctx);
                        ctx->fs_symlinks_count++;
                        if (ext2fs_inode_data_blocks(fs, inode) == 0) {
index a336755..56f352b 100644 (file)
@@ -1218,7 +1218,7 @@ extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                 && !e2fsck_pass1_check_device_inode(fs, &inode))
                problem = PR_2_BAD_SOCKET;
        else if (LINUX_S_ISLNK(inode.i_mode)
-                && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
+                && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
                problem = PR_2_INVALID_SYMLINK;
        }