0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/buffer_head.h>
0012 #include <linux/module.h>
0013 #include <linux/fs.h>
0014 #include "efs.h"
0015 #include <linux/efs_fs_sb.h>
0016
0017 static int efs_read_folio(struct file *file, struct folio *folio)
0018 {
0019 return block_read_full_folio(folio, efs_get_block);
0020 }
0021
0022 static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
0023 {
0024 return generic_block_bmap(mapping,block,efs_get_block);
0025 }
0026
0027 static const struct address_space_operations efs_aops = {
0028 .read_folio = efs_read_folio,
0029 .bmap = _efs_bmap
0030 };
0031
0032 static inline void extent_copy(efs_extent *src, efs_extent *dst) {
0033
0034
0035
0036
0037
0038
0039 dst->cooked.ex_magic = (unsigned int) src->raw[0];
0040 dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) |
0041 ((unsigned int) src->raw[2] << 8) |
0042 ((unsigned int) src->raw[3] << 0);
0043 dst->cooked.ex_length = (unsigned int) src->raw[4];
0044 dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
0045 ((unsigned int) src->raw[6] << 8) |
0046 ((unsigned int) src->raw[7] << 0);
0047 return;
0048 }
0049
0050 struct inode *efs_iget(struct super_block *super, unsigned long ino)
0051 {
0052 int i, inode_index;
0053 dev_t device;
0054 u32 rdev;
0055 struct buffer_head *bh;
0056 struct efs_sb_info *sb = SUPER_INFO(super);
0057 struct efs_inode_info *in;
0058 efs_block_t block, offset;
0059 struct efs_dinode *efs_inode;
0060 struct inode *inode;
0061
0062 inode = iget_locked(super, ino);
0063 if (!inode)
0064 return ERR_PTR(-ENOMEM);
0065 if (!(inode->i_state & I_NEW))
0066 return inode;
0067
0068 in = INODE_INFO(inode);
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 inode_index = inode->i_ino /
0083 (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
0084
0085 block = sb->fs_start + sb->first_block +
0086 (sb->group_size * (inode_index / sb->inode_blocks)) +
0087 (inode_index % sb->inode_blocks);
0088
0089 offset = (inode->i_ino %
0090 (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
0091 sizeof(struct efs_dinode);
0092
0093 bh = sb_bread(inode->i_sb, block);
0094 if (!bh) {
0095 pr_warn("%s() failed at block %d\n", __func__, block);
0096 goto read_inode_error;
0097 }
0098
0099 efs_inode = (struct efs_dinode *) (bh->b_data + offset);
0100
0101 inode->i_mode = be16_to_cpu(efs_inode->di_mode);
0102 set_nlink(inode, be16_to_cpu(efs_inode->di_nlink));
0103 i_uid_write(inode, (uid_t)be16_to_cpu(efs_inode->di_uid));
0104 i_gid_write(inode, (gid_t)be16_to_cpu(efs_inode->di_gid));
0105 inode->i_size = be32_to_cpu(efs_inode->di_size);
0106 inode->i_atime.tv_sec = be32_to_cpu(efs_inode->di_atime);
0107 inode->i_mtime.tv_sec = be32_to_cpu(efs_inode->di_mtime);
0108 inode->i_ctime.tv_sec = be32_to_cpu(efs_inode->di_ctime);
0109 inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
0110
0111
0112 if (inode->i_size == 0) {
0113 inode->i_blocks = 0;
0114 } else {
0115 inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
0116 }
0117
0118 rdev = be16_to_cpu(efs_inode->di_u.di_dev.odev);
0119 if (rdev == 0xffff) {
0120 rdev = be32_to_cpu(efs_inode->di_u.di_dev.ndev);
0121 if (sysv_major(rdev) > 0xfff)
0122 device = 0;
0123 else
0124 device = MKDEV(sysv_major(rdev), sysv_minor(rdev));
0125 } else
0126 device = old_decode_dev(rdev);
0127
0128
0129 in->numextents = be16_to_cpu(efs_inode->di_numextents);
0130 in->lastextent = 0;
0131
0132
0133 for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
0134 extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
0135 if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
0136 pr_warn("extent %d has bad magic number in inode %lu\n",
0137 i, inode->i_ino);
0138 brelse(bh);
0139 goto read_inode_error;
0140 }
0141 }
0142
0143 brelse(bh);
0144 pr_debug("efs_iget(): inode %lu, extents %d, mode %o\n",
0145 inode->i_ino, in->numextents, inode->i_mode);
0146 switch (inode->i_mode & S_IFMT) {
0147 case S_IFDIR:
0148 inode->i_op = &efs_dir_inode_operations;
0149 inode->i_fop = &efs_dir_operations;
0150 break;
0151 case S_IFREG:
0152 inode->i_fop = &generic_ro_fops;
0153 inode->i_data.a_ops = &efs_aops;
0154 break;
0155 case S_IFLNK:
0156 inode->i_op = &page_symlink_inode_operations;
0157 inode_nohighmem(inode);
0158 inode->i_data.a_ops = &efs_symlink_aops;
0159 break;
0160 case S_IFCHR:
0161 case S_IFBLK:
0162 case S_IFIFO:
0163 init_special_inode(inode, inode->i_mode, device);
0164 break;
0165 default:
0166 pr_warn("unsupported inode mode %o\n", inode->i_mode);
0167 goto read_inode_error;
0168 break;
0169 }
0170
0171 unlock_new_inode(inode);
0172 return inode;
0173
0174 read_inode_error:
0175 pr_warn("failed to read inode %lu\n", inode->i_ino);
0176 iget_failed(inode);
0177 return ERR_PTR(-EIO);
0178 }
0179
0180 static inline efs_block_t
0181 efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
0182 efs_block_t start;
0183 efs_block_t length;
0184 efs_block_t offset;
0185
0186
0187
0188
0189
0190 start = ptr->cooked.ex_bn;
0191 length = ptr->cooked.ex_length;
0192 offset = ptr->cooked.ex_offset;
0193
0194 if ((block >= offset) && (block < offset+length)) {
0195 return(sb->fs_start + start + block - offset);
0196 } else {
0197 return 0;
0198 }
0199 }
0200
0201 efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
0202 struct efs_sb_info *sb = SUPER_INFO(inode->i_sb);
0203 struct efs_inode_info *in = INODE_INFO(inode);
0204 struct buffer_head *bh = NULL;
0205
0206 int cur, last, first = 1;
0207 int ibase, ioffset, dirext, direxts, indext, indexts;
0208 efs_block_t iblock, result = 0, lastblock = 0;
0209 efs_extent ext, *exts;
0210
0211 last = in->lastextent;
0212
0213 if (in->numextents <= EFS_DIRECTEXTENTS) {
0214
0215 if ((result = efs_extent_check(&in->extents[last], block, sb)))
0216 return result;
0217
0218
0219 if (in->numextents == 1) {
0220 pr_err("%s() failed to map (1 extent)\n", __func__);
0221 return 0;
0222 }
0223
0224 direxts = in->numextents;
0225
0226
0227
0228
0229
0230 for(dirext = 1; dirext < direxts; dirext++) {
0231 cur = (last + dirext) % in->numextents;
0232 if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
0233 in->lastextent = cur;
0234 return result;
0235 }
0236 }
0237
0238 pr_err("%s() failed to map block %u (dir)\n", __func__, block);
0239 return 0;
0240 }
0241
0242 pr_debug("%s(): indirect search for logical block %u\n",
0243 __func__, block);
0244 direxts = in->extents[0].cooked.ex_offset;
0245 indexts = in->numextents;
0246
0247 for(indext = 0; indext < indexts; indext++) {
0248 cur = (last + indext) % indexts;
0249
0250
0251
0252
0253
0254
0255
0256
0257 ibase = 0;
0258 for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
0259 ibase += in->extents[dirext].cooked.ex_length *
0260 (EFS_BLOCKSIZE / sizeof(efs_extent));
0261 }
0262
0263 if (dirext == direxts) {
0264
0265 pr_err("couldn't find direct extent for indirect extent %d (block %u)\n",
0266 cur, block);
0267 if (bh) brelse(bh);
0268 return 0;
0269 }
0270
0271
0272 iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
0273 (cur - ibase) /
0274 (EFS_BLOCKSIZE / sizeof(efs_extent));
0275 ioffset = (cur - ibase) %
0276 (EFS_BLOCKSIZE / sizeof(efs_extent));
0277
0278 if (first || lastblock != iblock) {
0279 if (bh) brelse(bh);
0280
0281 bh = sb_bread(inode->i_sb, iblock);
0282 if (!bh) {
0283 pr_err("%s() failed at block %d\n",
0284 __func__, iblock);
0285 return 0;
0286 }
0287 pr_debug("%s(): read indirect extent block %d\n",
0288 __func__, iblock);
0289 first = 0;
0290 lastblock = iblock;
0291 }
0292
0293 exts = (efs_extent *) bh->b_data;
0294
0295 extent_copy(&(exts[ioffset]), &ext);
0296
0297 if (ext.cooked.ex_magic != 0) {
0298 pr_err("extent %d has bad magic number in block %d\n",
0299 cur, iblock);
0300 if (bh) brelse(bh);
0301 return 0;
0302 }
0303
0304 if ((result = efs_extent_check(&ext, block, sb))) {
0305 if (bh) brelse(bh);
0306 in->lastextent = cur;
0307 return result;
0308 }
0309 }
0310 if (bh) brelse(bh);
0311 pr_err("%s() failed to map block %u (indir)\n", __func__, block);
0312 return 0;
0313 }
0314
0315 MODULE_LICENSE("GPL");