Commit 4b5397dc24ab12afaac85be3d0863b7f6eb8b0f0

Authored by Phillip Lougher
1 parent b57f95a382

squashfs: add xattr id support

This patch adds support for mapping xattr ids (stored in inodes)
into the on-disk location of the xattrs themselves.

Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>

Showing 6 changed files with 161 additions and 4 deletions Side-by-side Diff

fs/squashfs/Makefile
... ... @@ -5,4 +5,5 @@
5 5 obj-$(CONFIG_SQUASHFS) += squashfs.o
6 6 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
7 7 squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
  8 +squashfs-y += xattr_id.o
fs/squashfs/squashfs.h
... ... @@ -73,6 +73,12 @@
73 73 unsigned int);
74 74 extern int squashfs_read_inode(struct inode *, long long);
75 75  
  76 +/* xattr_id.c */
  77 +extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *,
  78 + int *, long long *);
  79 +extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64,
  80 + u64 *, int *);
  81 +
76 82 /*
77 83 * Inodes, files and decompressor operations
78 84 */
fs/squashfs/squashfs_fs.h
... ... @@ -174,7 +174,25 @@
174 174  
175 175 #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\
176 176 sizeof(u64))
  177 +/* xattr id lookup table defines */
  178 +#define SQUASHFS_XATTR_BYTES(A) ((A) * sizeof(struct squashfs_xattr_id))
177 179  
  180 +#define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \
  181 + SQUASHFS_METADATA_SIZE)
  182 +
  183 +#define SQUASHFS_XATTR_BLOCK_OFFSET(A) (SQUASHFS_XATTR_BYTES(A) % \
  184 + SQUASHFS_METADATA_SIZE)
  185 +
  186 +#define SQUASHFS_XATTR_BLOCKS(A) ((SQUASHFS_XATTR_BYTES(A) + \
  187 + SQUASHFS_METADATA_SIZE - 1) / \
  188 + SQUASHFS_METADATA_SIZE)
  189 +
  190 +#define SQUASHFS_XATTR_BLOCK_BYTES(A) (SQUASHFS_XATTR_BLOCKS(A) *\
  191 + sizeof(u64))
  192 +#define SQUASHFS_XATTR_BLK(A) ((unsigned int) ((A) >> 16))
  193 +
  194 +#define SQUASHFS_XATTR_OFFSET(A) ((unsigned int) ((A) & 0xffff))
  195 +
178 196 /* cached data constants for filesystem */
179 197 #define SQUASHFS_CACHED_BLKS 8
180 198  
... ... @@ -228,7 +246,7 @@
228 246 __le64 root_inode;
229 247 __le64 bytes_used;
230 248 __le64 id_table_start;
231   - __le64 xattr_table_start;
  249 + __le64 xattr_id_table_start;
232 250 __le64 inode_table_start;
233 251 __le64 directory_table_start;
234 252 __le64 fragment_table_start;
... ... @@ -375,6 +393,18 @@
375 393 __le64 start_block;
376 394 __le32 size;
377 395 unsigned int unused;
  396 +};
  397 +
  398 +struct squashfs_xattr_id {
  399 + __le64 xattr;
  400 + __le32 count;
  401 + __le32 size;
  402 +};
  403 +
  404 +struct squashfs_xattr_id_table {
  405 + __le64 xattr_table_start;
  406 + __le32 xattr_ids;
  407 + __le32 unused;
378 408 };
379 409  
380 410 #endif
fs/squashfs/squashfs_fs_sb.h
... ... @@ -61,6 +61,7 @@
61 61 int next_meta_index;
62 62 __le64 *id_table;
63 63 __le64 *fragment_index;
  64 + __le64 *xattr_id_table;
64 65 struct mutex read_data_mutex;
65 66 struct mutex meta_index_mutex;
66 67 struct meta_index *meta_index;
67 68  
... ... @@ -68,10 +69,12 @@
68 69 __le64 *inode_lookup_table;
69 70 u64 inode_table;
70 71 u64 directory_table;
  72 + u64 xattr_table;
71 73 unsigned int block_size;
72 74 unsigned short block_log;
73 75 long long bytes_used;
74 76 unsigned int inodes;
  77 + int xattr_ids;
75 78 };
76 79 #endif
... ... @@ -36,6 +36,7 @@
36 36 #include <linux/init.h>
37 37 #include <linux/module.h>
38 38 #include <linux/magic.h>
  39 +#include <linux/xattr.h>
39 40  
40 41 #include "squashfs_fs.h"
41 42 #include "squashfs_fs_sb.h"
... ... @@ -82,7 +83,7 @@
82 83 long long root_inode;
83 84 unsigned short flags;
84 85 unsigned int fragments;
85   - u64 lookup_table_start;
  86 + u64 lookup_table_start, xattr_id_table_start;
86 87 int err;
87 88  
88 89 TRACE("Entered squashfs_fill_superblock\n");
... ... @@ -143,7 +144,7 @@
143 144 * Check if there's xattrs in the filesystem. These are not
144 145 * supported in this version, so warn that they will be ignored.
145 146 */
146   - if (le64_to_cpu(sblk->xattr_table_start) != SQUASHFS_INVALID_BLK)
  147 + if (le64_to_cpu(sblk->xattr_id_table_start) != SQUASHFS_INVALID_BLK)
147 148 ERROR("Xattrs in filesystem, these will be ignored\n");
148 149  
149 150 /* Check the filesystem does not extend beyond the end of the
... ... @@ -253,7 +254,7 @@
253 254 allocate_lookup_table:
254 255 lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
255 256 if (lookup_table_start == SQUASHFS_INVALID_BLK)
256   - goto allocate_root;
  257 + goto allocate_xattr_table;
257 258  
258 259 /* Allocate and read inode lookup table */
259 260 msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
... ... @@ -266,6 +267,19 @@
266 267  
267 268 sb->s_export_op = &squashfs_export_ops;
268 269  
  270 +allocate_xattr_table:
  271 + xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
  272 + if (xattr_id_table_start == SQUASHFS_INVALID_BLK)
  273 + goto allocate_root;
  274 +
  275 + /* Allocate and read xattr id lookup table */
  276 + msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
  277 + xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
  278 + if (IS_ERR(msblk->xattr_id_table)) {
  279 + err = PTR_ERR(msblk->xattr_id_table);
  280 + msblk->xattr_id_table = NULL;
  281 + goto failed_mount;
  282 + }
269 283 allocate_root:
270 284 root = new_inode(sb);
271 285 if (!root) {
... ... @@ -301,6 +315,7 @@
301 315 kfree(msblk->inode_lookup_table);
302 316 kfree(msblk->fragment_index);
303 317 kfree(msblk->id_table);
  318 + kfree(msblk->xattr_id_table);
304 319 kfree(sb->s_fs_info);
305 320 sb->s_fs_info = NULL;
306 321 kfree(sblk);
... ... @@ -355,6 +370,7 @@
355 370 kfree(sbi->fragment_index);
356 371 kfree(sbi->meta_index);
357 372 kfree(sbi->inode_lookup_table);
  373 + kfree(sbi->xattr_id_table);
358 374 kfree(sb->s_fs_info);
359 375 sb->s_fs_info = NULL;
360 376 }
fs/squashfs/xattr_id.c
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2010
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * xattr_id.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to map the 32-bit xattr id stored in the inode
  26 + * into the on disk location of the xattr data.
  27 + */
  28 +
  29 +#include <linux/fs.h>
  30 +#include <linux/vfs.h>
  31 +#include <linux/slab.h>
  32 +
  33 +#include "squashfs_fs.h"
  34 +#include "squashfs_fs_sb.h"
  35 +#include "squashfs_fs_i.h"
  36 +#include "squashfs.h"
  37 +
  38 +/*
  39 + * Map xattr id using the xattr id look up table
  40 + */
  41 +int squashfs_xattr_lookup(struct super_block *sb, unsigned int index,
  42 + int *count, int *size, long long *xattr)
  43 +{
  44 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  45 + int block = SQUASHFS_XATTR_BLOCK(index);
  46 + int offset = SQUASHFS_XATTR_BLOCK_OFFSET(index);
  47 + u64 start_block = le64_to_cpu(msblk->xattr_id_table[block]);
  48 + struct squashfs_xattr_id id;
  49 + int err;
  50 +
  51 + err = squashfs_read_metadata(sb, &id, &start_block, &offset,
  52 + sizeof(id));
  53 + if (err < 0)
  54 + return err;
  55 +
  56 + *xattr = le64_to_cpu(id.xattr);
  57 + *size = le32_to_cpu(id.size);
  58 + *count = le32_to_cpu(id.count);
  59 + return 0;
  60 +}
  61 +
  62 +
  63 +/*
  64 + * Read uncompressed xattr id lookup table indexes from disk into memory
  65 + */
  66 +__le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start,
  67 + u64 *xattr_table_start, int *xattr_ids)
  68 +{
  69 + unsigned int len;
  70 + __le64 *xid_table;
  71 + struct squashfs_xattr_id_table id_table;
  72 + int err;
  73 +
  74 + err = squashfs_read_table(sb, &id_table, start, sizeof(id_table));
  75 + if (err < 0) {
  76 + ERROR("unable to read xattr id table\n");
  77 + return ERR_PTR(err);
  78 + }
  79 + *xattr_table_start = le64_to_cpu(id_table.xattr_table_start);
  80 + *xattr_ids = le32_to_cpu(id_table.xattr_ids);
  81 + len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids);
  82 +
  83 + TRACE("In read_xattr_index_table, length %d\n", len);
  84 +
  85 + /* Allocate xattr id lookup table indexes */
  86 + xid_table = kmalloc(len, GFP_KERNEL);
  87 + if (xid_table == NULL) {
  88 + ERROR("Failed to allocate xattr id index table\n");
  89 + return ERR_PTR(-ENOMEM);
  90 + }
  91 +
  92 + err = squashfs_read_table(sb, xid_table, start + sizeof(id_table), len);
  93 + if (err < 0) {
  94 + ERROR("unable to read xattr id index table\n");
  95 + kfree(xid_table);
  96 + return ERR_PTR(err);
  97 + }
  98 +
  99 + return xid_table;
  100 +}