1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Squashfs - a compressed read only filesystem for Linux
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
6*4882a593Smuzhiyun * Phillip Lougher <phillip@squashfs.org.uk>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * inode.c
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun * This file implements code to create and read inodes from disk.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Inodes in Squashfs are identified by a 48-bit inode which encodes the
15*4882a593Smuzhiyun * location of the compressed metadata block containing the inode, and the byte
16*4882a593Smuzhiyun * offset into that block where the inode is placed (<block, offset>).
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * To maximise compression there are different inodes for each file type
19*4882a593Smuzhiyun * (regular file, directory, device, etc.), the inode contents and length
20*4882a593Smuzhiyun * varying with the type.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * To further maximise compression, two types of regular file inode and
23*4882a593Smuzhiyun * directory inode are defined: inodes optimised for frequently occurring
24*4882a593Smuzhiyun * regular files and directories, and extended types where extra
25*4882a593Smuzhiyun * information has to be stored.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <linux/fs.h>
29*4882a593Smuzhiyun #include <linux/vfs.h>
30*4882a593Smuzhiyun #include <linux/xattr.h>
31*4882a593Smuzhiyun #include <linux/pagemap.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include "squashfs_fs.h"
34*4882a593Smuzhiyun #include "squashfs_fs_sb.h"
35*4882a593Smuzhiyun #include "squashfs_fs_i.h"
36*4882a593Smuzhiyun #include "squashfs.h"
37*4882a593Smuzhiyun #include "xattr.h"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun * Initialise VFS inode with the base inode information common to all
41*4882a593Smuzhiyun * Squashfs inode types. Sqsh_ino contains the unswapped base inode
42*4882a593Smuzhiyun * off disk.
43*4882a593Smuzhiyun */
squashfs_new_inode(struct super_block * sb,struct inode * inode,struct squashfs_base_inode * sqsh_ino)44*4882a593Smuzhiyun static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
45*4882a593Smuzhiyun struct squashfs_base_inode *sqsh_ino)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun uid_t i_uid;
48*4882a593Smuzhiyun gid_t i_gid;
49*4882a593Smuzhiyun int err;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
52*4882a593Smuzhiyun if (err)
53*4882a593Smuzhiyun return err;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->guid), &i_gid);
56*4882a593Smuzhiyun if (err)
57*4882a593Smuzhiyun return err;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun i_uid_write(inode, i_uid);
60*4882a593Smuzhiyun i_gid_write(inode, i_gid);
61*4882a593Smuzhiyun inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
62*4882a593Smuzhiyun inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
63*4882a593Smuzhiyun inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
64*4882a593Smuzhiyun inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
65*4882a593Smuzhiyun inode->i_mode = le16_to_cpu(sqsh_ino->mode);
66*4882a593Smuzhiyun inode->i_size = 0;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun return err;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun
squashfs_iget(struct super_block * sb,long long ino,unsigned int ino_number)72*4882a593Smuzhiyun struct inode *squashfs_iget(struct super_block *sb, long long ino,
73*4882a593Smuzhiyun unsigned int ino_number)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun struct inode *inode = iget_locked(sb, ino_number);
76*4882a593Smuzhiyun int err;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun TRACE("Entered squashfs_iget\n");
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (!inode)
81*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
82*4882a593Smuzhiyun if (!(inode->i_state & I_NEW))
83*4882a593Smuzhiyun return inode;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun err = squashfs_read_inode(inode, ino);
86*4882a593Smuzhiyun if (err) {
87*4882a593Smuzhiyun iget_failed(inode);
88*4882a593Smuzhiyun return ERR_PTR(err);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun unlock_new_inode(inode);
92*4882a593Smuzhiyun return inode;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /*
97*4882a593Smuzhiyun * Initialise VFS inode by reading inode from inode table (compressed
98*4882a593Smuzhiyun * metadata). The format and amount of data read depends on type.
99*4882a593Smuzhiyun */
squashfs_read_inode(struct inode * inode,long long ino)100*4882a593Smuzhiyun int squashfs_read_inode(struct inode *inode, long long ino)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun struct super_block *sb = inode->i_sb;
103*4882a593Smuzhiyun struct squashfs_sb_info *msblk = sb->s_fs_info;
104*4882a593Smuzhiyun u64 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
105*4882a593Smuzhiyun int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
106*4882a593Smuzhiyun union squashfs_inode squashfs_ino;
107*4882a593Smuzhiyun struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
108*4882a593Smuzhiyun int xattr_id = SQUASHFS_INVALID_XATTR;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun TRACE("Entered squashfs_read_inode\n");
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /*
113*4882a593Smuzhiyun * Read inode base common to all inode types.
114*4882a593Smuzhiyun */
115*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqshb_ino, &block,
116*4882a593Smuzhiyun &offset, sizeof(*sqshb_ino));
117*4882a593Smuzhiyun if (err < 0)
118*4882a593Smuzhiyun goto failed_read;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun err = squashfs_new_inode(sb, inode, sqshb_ino);
121*4882a593Smuzhiyun if (err)
122*4882a593Smuzhiyun goto failed_read;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
125*4882a593Smuzhiyun offset = SQUASHFS_INODE_OFFSET(ino);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun type = le16_to_cpu(sqshb_ino->inode_type);
128*4882a593Smuzhiyun switch (type) {
129*4882a593Smuzhiyun case SQUASHFS_REG_TYPE: {
130*4882a593Smuzhiyun unsigned int frag_offset, frag;
131*4882a593Smuzhiyun int frag_size;
132*4882a593Smuzhiyun u64 frag_blk;
133*4882a593Smuzhiyun struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
136*4882a593Smuzhiyun sizeof(*sqsh_ino));
137*4882a593Smuzhiyun if (err < 0)
138*4882a593Smuzhiyun goto failed_read;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun frag = le32_to_cpu(sqsh_ino->fragment);
141*4882a593Smuzhiyun if (frag != SQUASHFS_INVALID_FRAG) {
142*4882a593Smuzhiyun frag_offset = le32_to_cpu(sqsh_ino->offset);
143*4882a593Smuzhiyun frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
144*4882a593Smuzhiyun if (frag_size < 0) {
145*4882a593Smuzhiyun err = frag_size;
146*4882a593Smuzhiyun goto failed_read;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun } else {
149*4882a593Smuzhiyun frag_blk = SQUASHFS_INVALID_BLK;
150*4882a593Smuzhiyun frag_size = 0;
151*4882a593Smuzhiyun frag_offset = 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun set_nlink(inode, 1);
155*4882a593Smuzhiyun inode->i_size = le32_to_cpu(sqsh_ino->file_size);
156*4882a593Smuzhiyun inode->i_fop = &generic_ro_fops;
157*4882a593Smuzhiyun inode->i_mode |= S_IFREG;
158*4882a593Smuzhiyun inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
159*4882a593Smuzhiyun squashfs_i(inode)->fragment_block = frag_blk;
160*4882a593Smuzhiyun squashfs_i(inode)->fragment_size = frag_size;
161*4882a593Smuzhiyun squashfs_i(inode)->fragment_offset = frag_offset;
162*4882a593Smuzhiyun squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
163*4882a593Smuzhiyun squashfs_i(inode)->block_list_start = block;
164*4882a593Smuzhiyun squashfs_i(inode)->offset = offset;
165*4882a593Smuzhiyun inode->i_data.a_ops = &squashfs_aops;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun TRACE("File inode %x:%x, start_block %llx, block_list_start "
168*4882a593Smuzhiyun "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
169*4882a593Smuzhiyun offset, squashfs_i(inode)->start, block, offset);
170*4882a593Smuzhiyun break;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun case SQUASHFS_LREG_TYPE: {
173*4882a593Smuzhiyun unsigned int frag_offset, frag;
174*4882a593Smuzhiyun int frag_size;
175*4882a593Smuzhiyun u64 frag_blk;
176*4882a593Smuzhiyun struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
179*4882a593Smuzhiyun sizeof(*sqsh_ino));
180*4882a593Smuzhiyun if (err < 0)
181*4882a593Smuzhiyun goto failed_read;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun frag = le32_to_cpu(sqsh_ino->fragment);
184*4882a593Smuzhiyun if (frag != SQUASHFS_INVALID_FRAG) {
185*4882a593Smuzhiyun frag_offset = le32_to_cpu(sqsh_ino->offset);
186*4882a593Smuzhiyun frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
187*4882a593Smuzhiyun if (frag_size < 0) {
188*4882a593Smuzhiyun err = frag_size;
189*4882a593Smuzhiyun goto failed_read;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun } else {
192*4882a593Smuzhiyun frag_blk = SQUASHFS_INVALID_BLK;
193*4882a593Smuzhiyun frag_size = 0;
194*4882a593Smuzhiyun frag_offset = 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun xattr_id = le32_to_cpu(sqsh_ino->xattr);
198*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
199*4882a593Smuzhiyun inode->i_size = le64_to_cpu(sqsh_ino->file_size);
200*4882a593Smuzhiyun inode->i_op = &squashfs_inode_ops;
201*4882a593Smuzhiyun inode->i_fop = &generic_ro_fops;
202*4882a593Smuzhiyun inode->i_mode |= S_IFREG;
203*4882a593Smuzhiyun inode->i_blocks = (inode->i_size -
204*4882a593Smuzhiyun le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun squashfs_i(inode)->fragment_block = frag_blk;
207*4882a593Smuzhiyun squashfs_i(inode)->fragment_size = frag_size;
208*4882a593Smuzhiyun squashfs_i(inode)->fragment_offset = frag_offset;
209*4882a593Smuzhiyun squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
210*4882a593Smuzhiyun squashfs_i(inode)->block_list_start = block;
211*4882a593Smuzhiyun squashfs_i(inode)->offset = offset;
212*4882a593Smuzhiyun inode->i_data.a_ops = &squashfs_aops;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun TRACE("File inode %x:%x, start_block %llx, block_list_start "
215*4882a593Smuzhiyun "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
216*4882a593Smuzhiyun offset, squashfs_i(inode)->start, block, offset);
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun case SQUASHFS_DIR_TYPE: {
220*4882a593Smuzhiyun struct squashfs_dir_inode *sqsh_ino = &squashfs_ino.dir;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
223*4882a593Smuzhiyun sizeof(*sqsh_ino));
224*4882a593Smuzhiyun if (err < 0)
225*4882a593Smuzhiyun goto failed_read;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
228*4882a593Smuzhiyun inode->i_size = le16_to_cpu(sqsh_ino->file_size);
229*4882a593Smuzhiyun inode->i_op = &squashfs_dir_inode_ops;
230*4882a593Smuzhiyun inode->i_fop = &squashfs_dir_ops;
231*4882a593Smuzhiyun inode->i_mode |= S_IFDIR;
232*4882a593Smuzhiyun squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
233*4882a593Smuzhiyun squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
234*4882a593Smuzhiyun squashfs_i(inode)->dir_idx_cnt = 0;
235*4882a593Smuzhiyun squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun TRACE("Directory inode %x:%x, start_block %llx, offset %x\n",
238*4882a593Smuzhiyun SQUASHFS_INODE_BLK(ino), offset,
239*4882a593Smuzhiyun squashfs_i(inode)->start,
240*4882a593Smuzhiyun le16_to_cpu(sqsh_ino->offset));
241*4882a593Smuzhiyun break;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun case SQUASHFS_LDIR_TYPE: {
244*4882a593Smuzhiyun struct squashfs_ldir_inode *sqsh_ino = &squashfs_ino.ldir;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
247*4882a593Smuzhiyun sizeof(*sqsh_ino));
248*4882a593Smuzhiyun if (err < 0)
249*4882a593Smuzhiyun goto failed_read;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun xattr_id = le32_to_cpu(sqsh_ino->xattr);
252*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
253*4882a593Smuzhiyun inode->i_size = le32_to_cpu(sqsh_ino->file_size);
254*4882a593Smuzhiyun inode->i_op = &squashfs_dir_inode_ops;
255*4882a593Smuzhiyun inode->i_fop = &squashfs_dir_ops;
256*4882a593Smuzhiyun inode->i_mode |= S_IFDIR;
257*4882a593Smuzhiyun squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
258*4882a593Smuzhiyun squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
259*4882a593Smuzhiyun squashfs_i(inode)->dir_idx_start = block;
260*4882a593Smuzhiyun squashfs_i(inode)->dir_idx_offset = offset;
261*4882a593Smuzhiyun squashfs_i(inode)->dir_idx_cnt = le16_to_cpu(sqsh_ino->i_count);
262*4882a593Smuzhiyun squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun TRACE("Long directory inode %x:%x, start_block %llx, offset "
265*4882a593Smuzhiyun "%x\n", SQUASHFS_INODE_BLK(ino), offset,
266*4882a593Smuzhiyun squashfs_i(inode)->start,
267*4882a593Smuzhiyun le16_to_cpu(sqsh_ino->offset));
268*4882a593Smuzhiyun break;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun case SQUASHFS_SYMLINK_TYPE:
271*4882a593Smuzhiyun case SQUASHFS_LSYMLINK_TYPE: {
272*4882a593Smuzhiyun struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
275*4882a593Smuzhiyun sizeof(*sqsh_ino));
276*4882a593Smuzhiyun if (err < 0)
277*4882a593Smuzhiyun goto failed_read;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
280*4882a593Smuzhiyun inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
281*4882a593Smuzhiyun inode->i_op = &squashfs_symlink_inode_ops;
282*4882a593Smuzhiyun inode_nohighmem(inode);
283*4882a593Smuzhiyun inode->i_data.a_ops = &squashfs_symlink_aops;
284*4882a593Smuzhiyun inode->i_mode |= S_IFLNK;
285*4882a593Smuzhiyun squashfs_i(inode)->start = block;
286*4882a593Smuzhiyun squashfs_i(inode)->offset = offset;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun if (type == SQUASHFS_LSYMLINK_TYPE) {
289*4882a593Smuzhiyun __le32 xattr;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun err = squashfs_read_metadata(sb, NULL, &block,
292*4882a593Smuzhiyun &offset, inode->i_size);
293*4882a593Smuzhiyun if (err < 0)
294*4882a593Smuzhiyun goto failed_read;
295*4882a593Smuzhiyun err = squashfs_read_metadata(sb, &xattr, &block,
296*4882a593Smuzhiyun &offset, sizeof(xattr));
297*4882a593Smuzhiyun if (err < 0)
298*4882a593Smuzhiyun goto failed_read;
299*4882a593Smuzhiyun xattr_id = le32_to_cpu(xattr);
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
303*4882a593Smuzhiyun "%x\n", SQUASHFS_INODE_BLK(ino), offset,
304*4882a593Smuzhiyun block, offset);
305*4882a593Smuzhiyun break;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun case SQUASHFS_BLKDEV_TYPE:
308*4882a593Smuzhiyun case SQUASHFS_CHRDEV_TYPE: {
309*4882a593Smuzhiyun struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
310*4882a593Smuzhiyun unsigned int rdev;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
313*4882a593Smuzhiyun sizeof(*sqsh_ino));
314*4882a593Smuzhiyun if (err < 0)
315*4882a593Smuzhiyun goto failed_read;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun if (type == SQUASHFS_CHRDEV_TYPE)
318*4882a593Smuzhiyun inode->i_mode |= S_IFCHR;
319*4882a593Smuzhiyun else
320*4882a593Smuzhiyun inode->i_mode |= S_IFBLK;
321*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
322*4882a593Smuzhiyun rdev = le32_to_cpu(sqsh_ino->rdev);
323*4882a593Smuzhiyun init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun TRACE("Device inode %x:%x, rdev %x\n",
326*4882a593Smuzhiyun SQUASHFS_INODE_BLK(ino), offset, rdev);
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun case SQUASHFS_LBLKDEV_TYPE:
330*4882a593Smuzhiyun case SQUASHFS_LCHRDEV_TYPE: {
331*4882a593Smuzhiyun struct squashfs_ldev_inode *sqsh_ino = &squashfs_ino.ldev;
332*4882a593Smuzhiyun unsigned int rdev;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
335*4882a593Smuzhiyun sizeof(*sqsh_ino));
336*4882a593Smuzhiyun if (err < 0)
337*4882a593Smuzhiyun goto failed_read;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (type == SQUASHFS_LCHRDEV_TYPE)
340*4882a593Smuzhiyun inode->i_mode |= S_IFCHR;
341*4882a593Smuzhiyun else
342*4882a593Smuzhiyun inode->i_mode |= S_IFBLK;
343*4882a593Smuzhiyun xattr_id = le32_to_cpu(sqsh_ino->xattr);
344*4882a593Smuzhiyun inode->i_op = &squashfs_inode_ops;
345*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
346*4882a593Smuzhiyun rdev = le32_to_cpu(sqsh_ino->rdev);
347*4882a593Smuzhiyun init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun TRACE("Device inode %x:%x, rdev %x\n",
350*4882a593Smuzhiyun SQUASHFS_INODE_BLK(ino), offset, rdev);
351*4882a593Smuzhiyun break;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun case SQUASHFS_FIFO_TYPE:
354*4882a593Smuzhiyun case SQUASHFS_SOCKET_TYPE: {
355*4882a593Smuzhiyun struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
358*4882a593Smuzhiyun sizeof(*sqsh_ino));
359*4882a593Smuzhiyun if (err < 0)
360*4882a593Smuzhiyun goto failed_read;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if (type == SQUASHFS_FIFO_TYPE)
363*4882a593Smuzhiyun inode->i_mode |= S_IFIFO;
364*4882a593Smuzhiyun else
365*4882a593Smuzhiyun inode->i_mode |= S_IFSOCK;
366*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
367*4882a593Smuzhiyun init_special_inode(inode, inode->i_mode, 0);
368*4882a593Smuzhiyun break;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun case SQUASHFS_LFIFO_TYPE:
371*4882a593Smuzhiyun case SQUASHFS_LSOCKET_TYPE: {
372*4882a593Smuzhiyun struct squashfs_lipc_inode *sqsh_ino = &squashfs_ino.lipc;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
375*4882a593Smuzhiyun sizeof(*sqsh_ino));
376*4882a593Smuzhiyun if (err < 0)
377*4882a593Smuzhiyun goto failed_read;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun if (type == SQUASHFS_LFIFO_TYPE)
380*4882a593Smuzhiyun inode->i_mode |= S_IFIFO;
381*4882a593Smuzhiyun else
382*4882a593Smuzhiyun inode->i_mode |= S_IFSOCK;
383*4882a593Smuzhiyun xattr_id = le32_to_cpu(sqsh_ino->xattr);
384*4882a593Smuzhiyun inode->i_op = &squashfs_inode_ops;
385*4882a593Smuzhiyun set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
386*4882a593Smuzhiyun init_special_inode(inode, inode->i_mode, 0);
387*4882a593Smuzhiyun break;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun default:
390*4882a593Smuzhiyun ERROR("Unknown inode type %d in squashfs_iget!\n", type);
391*4882a593Smuzhiyun return -EINVAL;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun if (xattr_id != SQUASHFS_INVALID_XATTR && msblk->xattr_id_table) {
395*4882a593Smuzhiyun err = squashfs_xattr_lookup(sb, xattr_id,
396*4882a593Smuzhiyun &squashfs_i(inode)->xattr_count,
397*4882a593Smuzhiyun &squashfs_i(inode)->xattr_size,
398*4882a593Smuzhiyun &squashfs_i(inode)->xattr);
399*4882a593Smuzhiyun if (err < 0)
400*4882a593Smuzhiyun goto failed_read;
401*4882a593Smuzhiyun inode->i_blocks += ((squashfs_i(inode)->xattr_size - 1) >> 9)
402*4882a593Smuzhiyun + 1;
403*4882a593Smuzhiyun } else
404*4882a593Smuzhiyun squashfs_i(inode)->xattr_count = 0;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun return 0;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun failed_read:
409*4882a593Smuzhiyun ERROR("Unable to read inode 0x%llx\n", ino);
410*4882a593Smuzhiyun return err;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun const struct inode_operations squashfs_inode_ops = {
415*4882a593Smuzhiyun .listxattr = squashfs_listxattr
416*4882a593Smuzhiyun };
417*4882a593Smuzhiyun
418