- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.git] / fs / squashfs / inode.c
index 49daaf6..62e63ad 100644 (file)
 
 #include <linux/fs.h>
 #include <linux/vfs.h>
+#include <linux/xattr.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
+#include "xattr.h"
 
 /*
  * Initialise VFS inode with the base inode information common to all
@@ -111,6 +113,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
        int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
        union squashfs_inode squashfs_ino;
        struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
+       int xattr_id = SQUASHFS_INVALID_XATTR;
 
        TRACE("Entered squashfs_read_inode\n");
 
@@ -199,8 +202,10 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                        frag_offset = 0;
                }
 
+               xattr_id = le32_to_cpu(sqsh_ino->xattr);
                inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
                inode->i_size = le64_to_cpu(sqsh_ino->file_size);
+               inode->i_op = &squashfs_inode_ops;
                inode->i_fop = &generic_ro_fops;
                inode->i_mode |= S_IFREG;
                inode->i_blocks = ((inode->i_size -
@@ -251,6 +256,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                if (err < 0)
                        goto failed_read;
 
+               xattr_id = le32_to_cpu(sqsh_ino->xattr);
                inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
                inode->i_size = le32_to_cpu(sqsh_ino->file_size);
                inode->i_op = &squashfs_dir_inode_ops;
@@ -280,21 +286,33 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 
                inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
                inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
-               inode->i_op = &page_symlink_inode_operations;
+               inode->i_op = &squashfs_symlink_inode_ops;
                inode->i_data.a_ops = &squashfs_symlink_aops;
                inode->i_mode |= S_IFLNK;
                squashfs_i(inode)->start = block;
                squashfs_i(inode)->offset = offset;
 
+               if (type == SQUASHFS_LSYMLINK_TYPE) {
+                       __le32 xattr;
+
+                       err = squashfs_read_metadata(sb, NULL, &block,
+                                               &offset, inode->i_size);
+                       if (err < 0)
+                               goto failed_read;
+                       err = squashfs_read_metadata(sb, &xattr, &block,
+                                               &offset, sizeof(xattr));
+                       if (err < 0)
+                               goto failed_read;
+                       xattr_id = le32_to_cpu(xattr);
+               }
+
                TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
                                "%x\n", SQUASHFS_INODE_BLK(ino), offset,
                                block, offset);
                break;
        }
        case SQUASHFS_BLKDEV_TYPE:
-       case SQUASHFS_CHRDEV_TYPE:
-       case SQUASHFS_LBLKDEV_TYPE:
-       case SQUASHFS_LCHRDEV_TYPE: {
+       case SQUASHFS_CHRDEV_TYPE: {
                struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
                unsigned int rdev;
 
@@ -315,10 +333,32 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                                SQUASHFS_INODE_BLK(ino), offset, rdev);
                break;
        }
+       case SQUASHFS_LBLKDEV_TYPE:
+       case SQUASHFS_LCHRDEV_TYPE: {
+               struct squashfs_ldev_inode *sqsh_ino = &squashfs_ino.ldev;
+               unsigned int rdev;
+
+               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
+                               sizeof(*sqsh_ino));
+               if (err < 0)
+                       goto failed_read;
+
+               if (type == SQUASHFS_LCHRDEV_TYPE)
+                       inode->i_mode |= S_IFCHR;
+               else
+                       inode->i_mode |= S_IFBLK;
+               xattr_id = le32_to_cpu(sqsh_ino->xattr);
+               inode->i_op = &squashfs_inode_ops;
+               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+               rdev = le32_to_cpu(sqsh_ino->rdev);
+               init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
+
+               TRACE("Device inode %x:%x, rdev %x\n",
+                               SQUASHFS_INODE_BLK(ino), offset, rdev);
+               break;
+       }
        case SQUASHFS_FIFO_TYPE:
-       case SQUASHFS_SOCKET_TYPE:
-       case SQUASHFS_LFIFO_TYPE:
-       case SQUASHFS_LSOCKET_TYPE: {
+       case SQUASHFS_SOCKET_TYPE: {
                struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
 
                err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
@@ -334,14 +374,52 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                init_special_inode(inode, inode->i_mode, 0);
                break;
        }
+       case SQUASHFS_LFIFO_TYPE:
+       case SQUASHFS_LSOCKET_TYPE: {
+               struct squashfs_lipc_inode *sqsh_ino = &squashfs_ino.lipc;
+
+               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
+                               sizeof(*sqsh_ino));
+               if (err < 0)
+                       goto failed_read;
+
+               if (type == SQUASHFS_LFIFO_TYPE)
+                       inode->i_mode |= S_IFIFO;
+               else
+                       inode->i_mode |= S_IFSOCK;
+               xattr_id = le32_to_cpu(sqsh_ino->xattr);
+               inode->i_op = &squashfs_inode_ops;
+               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+               init_special_inode(inode, inode->i_mode, 0);
+               break;
+       }
        default:
                ERROR("Unknown inode type %d in squashfs_iget!\n", type);
                return -EINVAL;
        }
 
+       if (xattr_id != SQUASHFS_INVALID_XATTR && msblk->xattr_id_table) {
+               err = squashfs_xattr_lookup(sb, xattr_id,
+                                       &squashfs_i(inode)->xattr_count,
+                                       &squashfs_i(inode)->xattr_size,
+                                       &squashfs_i(inode)->xattr);
+               if (err < 0)
+                       goto failed_read;
+               inode->i_blocks += ((squashfs_i(inode)->xattr_size - 1) >> 9)
+                               + 1;
+       } else
+               squashfs_i(inode)->xattr_count = 0;
+
        return 0;
 
 failed_read:
        ERROR("Unable to read inode 0x%llx\n", ino);
        return err;
 }
+
+
+const struct inode_operations squashfs_inode_ops = {
+       .getxattr = generic_getxattr,
+       .listxattr = squashfs_listxattr
+};
+