Commit 67f66cc6c728de183d9d43c243cb163c1ebd8e04

Authored by Phillip Lougher
1 parent f41d207cbe

squashfs: add new extended inode types

Add new extended inode types that store the xattr_id field.
Also add the necessary code changes to make xattrs visibile.

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

Showing 6 changed files with 135 additions and 16 deletions Side-by-side Diff

... ... @@ -40,6 +40,7 @@
40 40  
41 41 #include <linux/fs.h>
42 42 #include <linux/vfs.h>
  43 +#include <linux/xattr.h>
43 44  
44 45 #include "squashfs_fs.h"
45 46 #include "squashfs_fs_sb.h"
... ... @@ -111,6 +112,7 @@
111 112 int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
112 113 union squashfs_inode squashfs_ino;
113 114 struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
  115 + int xattr_id = SQUASHFS_INVALID_XATTR;
114 116  
115 117 TRACE("Entered squashfs_read_inode\n");
116 118  
117 119  
... ... @@ -199,8 +201,10 @@
199 201 frag_offset = 0;
200 202 }
201 203  
  204 + xattr_id = le32_to_cpu(sqsh_ino->xattr);
202 205 inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
203 206 inode->i_size = le64_to_cpu(sqsh_ino->file_size);
  207 + inode->i_op = &squashfs_inode_ops;
204 208 inode->i_fop = &generic_ro_fops;
205 209 inode->i_mode |= S_IFREG;
206 210 inode->i_blocks = ((inode->i_size -
... ... @@ -251,6 +255,7 @@
251 255 if (err < 0)
252 256 goto failed_read;
253 257  
  258 + xattr_id = le32_to_cpu(sqsh_ino->xattr);
254 259 inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
255 260 inode->i_size = le32_to_cpu(sqsh_ino->file_size);
256 261 inode->i_op = &squashfs_dir_inode_ops;
257 262  
258 263  
... ... @@ -280,21 +285,33 @@
280 285  
281 286 inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
282 287 inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
283   - inode->i_op = &page_symlink_inode_operations;
  288 + inode->i_op = &squashfs_symlink_inode_ops;
284 289 inode->i_data.a_ops = &squashfs_symlink_aops;
285 290 inode->i_mode |= S_IFLNK;
286 291 squashfs_i(inode)->start = block;
287 292 squashfs_i(inode)->offset = offset;
288 293  
  294 + if (type == SQUASHFS_LSYMLINK_TYPE) {
  295 + __le32 xattr;
  296 +
  297 + err = squashfs_read_metadata(sb, NULL, &block,
  298 + &offset, inode->i_size);
  299 + if (err < 0)
  300 + goto failed_read;
  301 + err = squashfs_read_metadata(sb, &xattr, &block,
  302 + &offset, sizeof(xattr));
  303 + if (err < 0)
  304 + goto failed_read;
  305 + xattr_id = le32_to_cpu(xattr);
  306 + }
  307 +
289 308 TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
290 309 "%x\n", SQUASHFS_INODE_BLK(ino), offset,
291 310 block, offset);
292 311 break;
293 312 }
294 313 case SQUASHFS_BLKDEV_TYPE:
295   - case SQUASHFS_CHRDEV_TYPE:
296   - case SQUASHFS_LBLKDEV_TYPE:
297   - case SQUASHFS_LCHRDEV_TYPE: {
  314 + case SQUASHFS_CHRDEV_TYPE: {
298 315 struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
299 316 unsigned int rdev;
300 317  
301 318  
... ... @@ -315,10 +332,32 @@
315 332 SQUASHFS_INODE_BLK(ino), offset, rdev);
316 333 break;
317 334 }
  335 + case SQUASHFS_LBLKDEV_TYPE:
  336 + case SQUASHFS_LCHRDEV_TYPE: {
  337 + struct squashfs_ldev_inode *sqsh_ino = &squashfs_ino.ldev;
  338 + unsigned int rdev;
  339 +
  340 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  341 + sizeof(*sqsh_ino));
  342 + if (err < 0)
  343 + goto failed_read;
  344 +
  345 + if (type == SQUASHFS_LCHRDEV_TYPE)
  346 + inode->i_mode |= S_IFCHR;
  347 + else
  348 + inode->i_mode |= S_IFBLK;
  349 + xattr_id = le32_to_cpu(sqsh_ino->xattr);
  350 + inode->i_op = &squashfs_inode_ops;
  351 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  352 + rdev = le32_to_cpu(sqsh_ino->rdev);
  353 + init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
  354 +
  355 + TRACE("Device inode %x:%x, rdev %x\n",
  356 + SQUASHFS_INODE_BLK(ino), offset, rdev);
  357 + break;
  358 + }
318 359 case SQUASHFS_FIFO_TYPE:
319   - case SQUASHFS_SOCKET_TYPE:
320   - case SQUASHFS_LFIFO_TYPE:
321   - case SQUASHFS_LSOCKET_TYPE: {
  360 + case SQUASHFS_SOCKET_TYPE: {
322 361 struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
323 362  
324 363 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
325 364  
326 365  
... ... @@ -334,15 +373,52 @@
334 373 init_special_inode(inode, inode->i_mode, 0);
335 374 break;
336 375 }
  376 + case SQUASHFS_LFIFO_TYPE:
  377 + case SQUASHFS_LSOCKET_TYPE: {
  378 + struct squashfs_lipc_inode *sqsh_ino = &squashfs_ino.lipc;
  379 +
  380 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  381 + sizeof(*sqsh_ino));
  382 + if (err < 0)
  383 + goto failed_read;
  384 +
  385 + if (type == SQUASHFS_LFIFO_TYPE)
  386 + inode->i_mode |= S_IFIFO;
  387 + else
  388 + inode->i_mode |= S_IFSOCK;
  389 + xattr_id = le32_to_cpu(sqsh_ino->xattr);
  390 + inode->i_op = &squashfs_inode_ops;
  391 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  392 + init_special_inode(inode, inode->i_mode, 0);
  393 + break;
  394 + }
337 395 default:
338 396 ERROR("Unknown inode type %d in squashfs_iget!\n", type);
339 397 return -EINVAL;
340 398 }
341 399  
  400 + if (xattr_id != SQUASHFS_INVALID_XATTR && msblk->xattr_id_table) {
  401 + err = squashfs_xattr_lookup(sb, xattr_id,
  402 + &squashfs_i(inode)->xattr_count,
  403 + &squashfs_i(inode)->xattr_size,
  404 + &squashfs_i(inode)->xattr);
  405 + if (err < 0)
  406 + goto failed_read;
  407 + inode->i_blocks += ((squashfs_i(inode)->xattr_size - 1) >> 9)
  408 + + 1;
  409 + } else
  410 + squashfs_i(inode)->xattr_count = 0;
  411 +
342 412 return 0;
343 413  
344 414 failed_read:
345 415 ERROR("Unable to read inode 0x%llx\n", ino);
346 416 return err;
347 417 }
  418 +
  419 +
  420 +const struct inode_operations squashfs_inode_ops = {
  421 + .getxattr = generic_getxattr,
  422 + .listxattr = squashfs_listxattr
  423 +};
... ... @@ -57,6 +57,7 @@
57 57 #include <linux/slab.h>
58 58 #include <linux/string.h>
59 59 #include <linux/dcache.h>
  60 +#include <linux/xattr.h>
60 61  
61 62 #include "squashfs_fs.h"
62 63 #include "squashfs_fs_sb.h"
... ... @@ -237,6 +238,8 @@
237 238  
238 239  
239 240 const struct inode_operations squashfs_dir_inode_ops = {
240   - .lookup = squashfs_lookup
  241 + .lookup = squashfs_lookup,
  242 + .getxattr = generic_getxattr,
  243 + .listxattr = squashfs_listxattr
241 244 };
fs/squashfs/squashfs.h
... ... @@ -73,6 +73,9 @@
73 73 unsigned int);
74 74 extern int squashfs_read_inode(struct inode *, long long);
75 75  
  76 +/* xattr.c */
  77 +extern ssize_t squashfs_listxattr(struct dentry *, char *, size_t);
  78 +
76 79 /* xattr_id.c */
77 80 extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *,
78 81 int *, long long *);
... ... @@ -80,7 +83,7 @@
80 83 u64 *, int *);
81 84  
82 85 /*
83   - * Inodes, files and decompressor operations
  86 + * Inodes, files, decompressor and xattr operations
84 87 */
85 88  
86 89 /* dir.c */
87 90  
... ... @@ -92,11 +95,18 @@
92 95 /* file.c */
93 96 extern const struct address_space_operations squashfs_aops;
94 97  
  98 +/* inode.c */
  99 +extern const struct inode_operations squashfs_inode_ops;
  100 +
95 101 /* namei.c */
96 102 extern const struct inode_operations squashfs_dir_inode_ops;
97 103  
98 104 /* symlink.c */
99 105 extern const struct address_space_operations squashfs_symlink_aops;
  106 +extern const struct inode_operations squashfs_symlink_inode_ops;
  107 +
  108 +/* xattr.c */
  109 +extern struct xattr_handler *squashfs_xattr_handlers[];
100 110  
101 111 /* zlib_wrapper.c */
102 112 extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
fs/squashfs/squashfs_fs.h
... ... @@ -287,6 +287,17 @@
287 287 __le32 nlink;
288 288 };
289 289  
  290 +struct squashfs_lipc_inode {
  291 + __le16 inode_type;
  292 + __le16 mode;
  293 + __le16 uid;
  294 + __le16 guid;
  295 + __le32 mtime;
  296 + __le32 inode_number;
  297 + __le32 nlink;
  298 + __le32 xattr;
  299 +};
  300 +
290 301 struct squashfs_dev_inode {
291 302 __le16 inode_type;
292 303 __le16 mode;
... ... @@ -298,6 +309,18 @@
298 309 __le32 rdev;
299 310 };
300 311  
  312 +struct squashfs_ldev_inode {
  313 + __le16 inode_type;
  314 + __le16 mode;
  315 + __le16 uid;
  316 + __le16 guid;
  317 + __le32 mtime;
  318 + __le32 inode_number;
  319 + __le32 nlink;
  320 + __le32 rdev;
  321 + __le32 xattr;
  322 +};
  323 +
301 324 struct squashfs_symlink_inode {
302 325 __le16 inode_type;
303 326 __le16 mode;
304 327  
... ... @@ -375,12 +398,14 @@
375 398 union squashfs_inode {
376 399 struct squashfs_base_inode base;
377 400 struct squashfs_dev_inode dev;
  401 + struct squashfs_ldev_inode ldev;
378 402 struct squashfs_symlink_inode symlink;
379 403 struct squashfs_reg_inode reg;
380 404 struct squashfs_lreg_inode lreg;
381 405 struct squashfs_dir_inode dir;
382 406 struct squashfs_ldir_inode ldir;
383 407 struct squashfs_ipc_inode ipc;
  408 + struct squashfs_lipc_inode lipc;
384 409 };
385 410  
386 411 struct squashfs_dir_entry {
... ... @@ -140,13 +140,6 @@
140 140 if (msblk->decompressor == NULL)
141 141 goto failed_mount;
142 142  
143   - /*
144   - * Check if there's xattrs in the filesystem. These are not
145   - * supported in this version, so warn that they will be ignored.
146   - */
147   - if (le64_to_cpu(sblk->xattr_id_table_start) != SQUASHFS_INVALID_BLK)
148   - ERROR("Xattrs in filesystem, these will be ignored\n");
149   -
150 143 /* Check the filesystem does not extend beyond the end of the
151 144 block device */
152 145 msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
... ... @@ -268,6 +261,7 @@
268 261 sb->s_export_op = &squashfs_export_ops;
269 262  
270 263 allocate_xattr_table:
  264 + sb->s_xattr = squashfs_xattr_handlers;
271 265 xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
272 266 if (xattr_id_table_start == SQUASHFS_INVALID_BLK)
273 267 goto allocate_root;
fs/squashfs/symlink.c
... ... @@ -35,6 +35,7 @@
35 35 #include <linux/kernel.h>
36 36 #include <linux/string.h>
37 37 #include <linux/pagemap.h>
  38 +#include <linux/xattr.h>
38 39  
39 40 #include "squashfs_fs.h"
40 41 #include "squashfs_fs_sb.h"
... ... @@ -113,5 +114,13 @@
113 114  
114 115 const struct address_space_operations squashfs_symlink_aops = {
115 116 .readpage = squashfs_symlink_readpage
  117 +};
  118 +
  119 +const struct inode_operations squashfs_symlink_inode_ops = {
  120 + .readlink = generic_readlink,
  121 + .follow_link = page_follow_link_light,
  122 + .put_link = page_put_link,
  123 + .getxattr = generic_getxattr,
  124 + .listxattr = squashfs_listxattr
116 125 };