1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2000-2001 Christoph Hellwig.
4 * Copyright (c) 2016 Krzysztof Blaszkowski
8 * Veritas filesystem driver - inode routines.
11 #include <linux/buffer_head.h>
12 #include <linux/pagemap.h>
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/namei.h>
18 #include "vxfs_inode.h"
19 #include "vxfs_extern.h"
24 * Dump inode contents (partially).
27 vxfs_dumpi(struct vxfs_inode_info
*vip
, ino_t ino
)
29 printk(KERN_DEBUG
"\n\n");
31 printk(KERN_DEBUG
"dumping vxfs inode %ld\n", ino
);
33 printk(KERN_DEBUG
"dumping unknown vxfs inode\n");
35 printk(KERN_DEBUG
"---------------------------\n");
36 printk(KERN_DEBUG
"mode is %x\n", vip
->vii_mode
);
37 printk(KERN_DEBUG
"nlink:%u, uid:%u, gid:%u\n",
38 vip
->vii_nlink
, vip
->vii_uid
, vip
->vii_gid
);
39 printk(KERN_DEBUG
"size:%Lx, blocks:%u\n",
40 vip
->vii_size
, vip
->vii_blocks
);
41 printk(KERN_DEBUG
"orgtype:%u\n", vip
->vii_orgtype
);
46 * vxfs_transmod - mode for a VxFS inode
50 * vxfs_transmod returns a Linux mode_t for a given
51 * VxFS inode structure.
53 static __inline__ umode_t
54 vxfs_transmod(struct vxfs_inode_info
*vip
)
56 umode_t ret
= vip
->vii_mode
& ~VXFS_TYPE_MASK
;
76 static inline void dip2vip_cpy(struct vxfs_sb_info
*sbi
,
77 struct vxfs_inode_info
*vip
, struct vxfs_dinode
*dip
)
79 struct inode
*inode
= &vip
->vfs_inode
;
81 vip
->vii_mode
= fs32_to_cpu(sbi
, dip
->vdi_mode
);
82 vip
->vii_nlink
= fs32_to_cpu(sbi
, dip
->vdi_nlink
);
83 vip
->vii_uid
= fs32_to_cpu(sbi
, dip
->vdi_uid
);
84 vip
->vii_gid
= fs32_to_cpu(sbi
, dip
->vdi_gid
);
85 vip
->vii_size
= fs64_to_cpu(sbi
, dip
->vdi_size
);
86 vip
->vii_atime
= fs32_to_cpu(sbi
, dip
->vdi_atime
);
87 vip
->vii_autime
= fs32_to_cpu(sbi
, dip
->vdi_autime
);
88 vip
->vii_mtime
= fs32_to_cpu(sbi
, dip
->vdi_mtime
);
89 vip
->vii_mutime
= fs32_to_cpu(sbi
, dip
->vdi_mutime
);
90 vip
->vii_ctime
= fs32_to_cpu(sbi
, dip
->vdi_ctime
);
91 vip
->vii_cutime
= fs32_to_cpu(sbi
, dip
->vdi_cutime
);
92 vip
->vii_orgtype
= dip
->vdi_orgtype
;
94 vip
->vii_blocks
= fs32_to_cpu(sbi
, dip
->vdi_blocks
);
95 vip
->vii_gen
= fs32_to_cpu(sbi
, dip
->vdi_gen
);
98 vip
->vii_dotdot
= fs32_to_cpu(sbi
, dip
->vdi_dotdot
);
99 else if (!VXFS_ISREG(vip
) && !VXFS_ISLNK(vip
))
100 vip
->vii_rdev
= fs32_to_cpu(sbi
, dip
->vdi_rdev
);
102 /* don't endian swap the fields that differ by orgtype */
103 memcpy(&vip
->vii_org
, &dip
->vdi_org
, sizeof(vip
->vii_org
));
105 inode
->i_mode
= vxfs_transmod(vip
);
106 i_uid_write(inode
, (uid_t
)vip
->vii_uid
);
107 i_gid_write(inode
, (gid_t
)vip
->vii_gid
);
109 set_nlink(inode
, vip
->vii_nlink
);
110 inode
->i_size
= vip
->vii_size
;
112 inode_set_atime(inode
, vip
->vii_atime
, 0);
113 inode_set_ctime(inode
, vip
->vii_ctime
, 0);
114 inode_set_mtime(inode
, vip
->vii_mtime
, 0);
116 inode
->i_blocks
= vip
->vii_blocks
;
117 inode
->i_generation
= vip
->vii_gen
;
121 * vxfs_blkiget - find inode based on extent #
122 * @sbp: superblock of the filesystem we search in
123 * @extent: number of the extent to search
124 * @ino: inode number to search
127 * vxfs_blkiget searches inode @ino in the filesystem described by
128 * @sbp in the extent @extent.
129 * Returns the matching VxFS inode on success, else a NULL pointer.
132 * While __vxfs_iget uses the pagecache vxfs_blkiget uses the
133 * buffercache. This function should not be used outside the
134 * read_super() method, otherwise the data may be incoherent.
137 vxfs_blkiget(struct super_block
*sbp
, u_long extent
, ino_t ino
)
139 struct buffer_head
*bp
;
141 u_long block
, offset
;
143 inode
= new_inode(sbp
);
146 inode
->i_ino
= get_next_ino();
148 block
= extent
+ ((ino
* VXFS_ISIZE
) / sbp
->s_blocksize
);
149 offset
= ((ino
% (sbp
->s_blocksize
/ VXFS_ISIZE
)) * VXFS_ISIZE
);
150 bp
= sb_bread(sbp
, block
);
152 if (bp
&& buffer_mapped(bp
)) {
153 struct vxfs_inode_info
*vip
= VXFS_INO(inode
);
154 struct vxfs_dinode
*dip
;
156 dip
= (struct vxfs_dinode
*)(bp
->b_data
+ offset
);
157 dip2vip_cpy(VXFS_SBI(sbp
), vip
, dip
);
158 vip
->vfs_inode
.i_mapping
->a_ops
= &vxfs_aops
;
160 vxfs_dumpi(vip
, ino
);
166 printk(KERN_WARNING
"vxfs: unable to read block %ld\n", block
);
173 * __vxfs_iget - generic find inode facility
174 * @ilistp: inode list
175 * @vip: VxFS inode to fill in
179 * Search the for inode number @ino in the filesystem
180 * described by @sbp. Use the specified inode table (@ilistp).
181 * Returns the matching inode on success, else an error code.
184 __vxfs_iget(struct inode
*ilistp
, struct vxfs_inode_info
*vip
, ino_t ino
)
189 offset
= (ino
% (PAGE_SIZE
/ VXFS_ISIZE
)) * VXFS_ISIZE
;
190 pp
= vxfs_get_page(ilistp
->i_mapping
, ino
* VXFS_ISIZE
/ PAGE_SIZE
);
193 struct vxfs_dinode
*dip
;
194 caddr_t kaddr
= (char *)page_address(pp
);
196 dip
= (struct vxfs_dinode
*)(kaddr
+ offset
);
197 dip2vip_cpy(VXFS_SBI(ilistp
->i_sb
), vip
, dip
);
198 vip
->vfs_inode
.i_mapping
->a_ops
= &vxfs_aops
;
200 vxfs_dumpi(vip
, ino
);
206 printk(KERN_WARNING
"vxfs: error on page 0x%p for inode %ld\n",
207 pp
, (unsigned long)ino
);
212 * vxfs_stiget - find inode using the structural inode list
213 * @sbp: VFS superblock
217 * Find inode @ino in the filesystem described by @sbp using
218 * the structural inode list.
219 * Returns the matching inode on success, else a NULL pointer.
222 vxfs_stiget(struct super_block
*sbp
, ino_t ino
)
227 inode
= new_inode(sbp
);
230 inode
->i_ino
= get_next_ino();
232 error
= __vxfs_iget(VXFS_SBI(sbp
)->vsi_stilist
, VXFS_INO(inode
), ino
);
242 * vxfs_iget - get an inode
243 * @sbp: the superblock to get the inode for
244 * @ino: the number of the inode to get
247 * vxfs_read_inode creates an inode, reads the disk inode for @ino and fills
248 * in all relevant fields in the new inode.
251 vxfs_iget(struct super_block
*sbp
, ino_t ino
)
253 struct vxfs_inode_info
*vip
;
254 const struct address_space_operations
*aops
;
258 ip
= iget_locked(sbp
, ino
);
260 return ERR_PTR(-ENOMEM
);
261 if (!(ip
->i_state
& I_NEW
))
265 error
= __vxfs_iget(VXFS_SBI(sbp
)->vsi_ilist
, vip
, ino
);
268 return ERR_PTR(error
);
271 if (VXFS_ISIMMED(vip
))
272 aops
= &vxfs_immed_aops
;
276 if (S_ISREG(ip
->i_mode
)) {
277 ip
->i_fop
= &generic_ro_fops
;
278 ip
->i_mapping
->a_ops
= aops
;
279 } else if (S_ISDIR(ip
->i_mode
)) {
280 ip
->i_op
= &vxfs_dir_inode_ops
;
281 ip
->i_fop
= &vxfs_dir_operations
;
282 ip
->i_mapping
->a_ops
= aops
;
283 } else if (S_ISLNK(ip
->i_mode
)) {
284 if (!VXFS_ISIMMED(vip
)) {
285 ip
->i_op
= &page_symlink_inode_operations
;
287 ip
->i_mapping
->a_ops
= &vxfs_aops
;
289 ip
->i_op
= &simple_symlink_inode_operations
;
290 ip
->i_link
= vip
->vii_immed
.vi_immed
;
291 nd_terminate_link(ip
->i_link
, ip
->i_size
,
292 sizeof(vip
->vii_immed
.vi_immed
) - 1);
295 init_special_inode(ip
, ip
->i_mode
, old_decode_dev(vip
->vii_rdev
));
297 unlock_new_inode(ip
);
302 * vxfs_evict_inode - remove inode from main memory
303 * @ip: inode to discard.
306 * vxfs_evict_inode() is called on the final iput and frees the private
310 vxfs_evict_inode(struct inode
*ip
)
312 truncate_inode_pages_final(&ip
->i_data
);