1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/sysv/ialloc.c 4 * 5 * minix/bitmap.c 6 * Copyright (C) 1991, 1992 Linus Torvalds 7 * 8 * ext/freelists.c 9 * Copyright (C) 1992 Remy Card (card@masi.ibp.fr) 10 * 11 * xenix/alloc.c 12 * Copyright (C) 1992 Doug Evans 13 * 14 * coh/alloc.c 15 * Copyright (C) 1993 Pascal Haible, Bruno Haible 16 * 17 * sysv/ialloc.c 18 * Copyright (C) 1993 Bruno Haible 19 * 20 * This file contains code for allocating/freeing inodes. 21 */ 22 23 #include <linux/kernel.h> 24 #include <linux/stddef.h> 25 #include <linux/sched.h> 26 #include <linux/stat.h> 27 #include <linux/string.h> 28 #include <linux/buffer_head.h> 29 #include <linux/writeback.h> 30 #include "sysv.h" 31 32 /* We don't trust the value of 33 sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes 34 but we nevertheless keep it up to date. */ 35 36 /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */ 37 38 /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */ 39 static inline sysv_ino_t * 40 sv_sb_fic_inode(struct super_block * sb, unsigned int i) 41 { 42 struct sysv_sb_info *sbi = SYSV_SB(sb); 43 44 if (sbi->s_bh1 == sbi->s_bh2) 45 return &sbi->s_sb_fic_inodes[i]; 46 else { 47 /* 512 byte Xenix FS */ 48 unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]); 49 if (offset < 512) 50 return (sysv_ino_t*)(sbi->s_sbd1 + offset); 51 else 52 return (sysv_ino_t*)(sbi->s_sbd2 + offset); 53 } 54 } 55 56 struct sysv_inode * 57 sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh) 58 { 59 struct sysv_sb_info *sbi = SYSV_SB(sb); 60 struct sysv_inode *res; 61 int block = sbi->s_firstinodezone + sbi->s_block_base; 62 63 block += (ino-1) >> sbi->s_inodes_per_block_bits; 64 *bh = sb_bread(sb, block); 65 if (!*bh) 66 return NULL; 67 res = (struct sysv_inode *)(*bh)->b_data; 68 return res + ((ino-1) & sbi->s_inodes_per_block_1); 69 } 70 71 static int refill_free_cache(struct super_block *sb) 72 { 73 struct sysv_sb_info *sbi = SYSV_SB(sb); 74 struct buffer_head * bh; 75 struct sysv_inode * raw_inode; 76 int i = 0, ino; 77 78 ino = SYSV_ROOT_INO+1; 79 raw_inode = sysv_raw_inode(sb, ino, &bh); 80 if (!raw_inode) 81 goto out; 82 while (ino <= sbi->s_ninodes) { 83 if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) { 84 *sv_sb_fic_inode(sb,i++) = cpu_to_fs16(SYSV_SB(sb), ino); 85 if (i == sbi->s_fic_size) 86 break; 87 } 88 if ((ino++ & sbi->s_inodes_per_block_1) == 0) { 89 brelse(bh); 90 raw_inode = sysv_raw_inode(sb, ino, &bh); 91 if (!raw_inode) 92 goto out; 93 } else 94 raw_inode++; 95 } 96 brelse(bh); 97 out: 98 return i; 99 } 100 101 void sysv_free_inode(struct inode * inode) 102 { 103 struct super_block *sb = inode->i_sb; 104 struct sysv_sb_info *sbi = SYSV_SB(sb); 105 unsigned int ino; 106 struct buffer_head * bh; 107 struct sysv_inode * raw_inode; 108 unsigned count; 109 110 sb = inode->i_sb; 111 ino = inode->i_ino; 112 if (ino <= SYSV_ROOT_INO || ino > sbi->s_ninodes) { 113 printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); 114 return; 115 } 116 raw_inode = sysv_raw_inode(sb, ino, &bh); 117 if (!raw_inode) { 118 printk("sysv_free_inode: unable to read inode block on device " 119 "%s\n", inode->i_sb->s_id); 120 return; 121 } 122 mutex_lock(&sbi->s_lock); 123 count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); 124 if (count < sbi->s_fic_size) { 125 *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino); 126 *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count); 127 } 128 fs16_add(sbi, sbi->s_sb_total_free_inodes, 1); 129 dirty_sb(sb); 130 memset(raw_inode, 0, sizeof(struct sysv_inode)); 131 mark_buffer_dirty(bh); 132 mutex_unlock(&sbi->s_lock); 133 brelse(bh); 134 } 135 136 struct inode * sysv_new_inode(const struct inode * dir, umode_t mode) 137 { 138 struct super_block *sb = dir->i_sb; 139 struct sysv_sb_info *sbi = SYSV_SB(sb); 140 struct inode *inode; 141 sysv_ino_t ino; 142 unsigned count; 143 struct writeback_control wbc = { 144 .sync_mode = WB_SYNC_NONE 145 }; 146 147 inode = new_inode(sb); 148 if (!inode) 149 return ERR_PTR(-ENOMEM); 150 151 mutex_lock(&sbi->s_lock); 152 count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count); 153 if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) { 154 count = refill_free_cache(sb); 155 if (count == 0) { 156 iput(inode); 157 mutex_unlock(&sbi->s_lock); 158 return ERR_PTR(-ENOSPC); 159 } 160 } 161 /* Now count > 0. */ 162 ino = *sv_sb_fic_inode(sb,--count); 163 *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count); 164 fs16_add(sbi, sbi->s_sb_total_free_inodes, -1); 165 dirty_sb(sb); 166 inode_init_owner(&nop_mnt_idmap, inode, dir, mode); 167 inode->i_ino = fs16_to_cpu(sbi, ino); 168 simple_inode_init_ts(inode); 169 inode->i_blocks = 0; 170 memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data)); 171 SYSV_I(inode)->i_dir_start_lookup = 0; 172 insert_inode_hash(inode); 173 mark_inode_dirty(inode); 174 175 sysv_write_inode(inode, &wbc); /* ensure inode not allocated again */ 176 mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ 177 /* That's it. */ 178 mutex_unlock(&sbi->s_lock); 179 return inode; 180 } 181 182 unsigned long sysv_count_free_inodes(struct super_block * sb) 183 { 184 struct sysv_sb_info *sbi = SYSV_SB(sb); 185 struct buffer_head * bh; 186 struct sysv_inode * raw_inode; 187 int ino, count, sb_count; 188 189 mutex_lock(&sbi->s_lock); 190 191 sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes); 192 193 if (0) 194 goto trust_sb; 195 196 /* this causes a lot of disk traffic ... */ 197 count = 0; 198 ino = SYSV_ROOT_INO+1; 199 raw_inode = sysv_raw_inode(sb, ino, &bh); 200 if (!raw_inode) 201 goto Eio; 202 while (ino <= sbi->s_ninodes) { 203 if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) 204 count++; 205 if ((ino++ & sbi->s_inodes_per_block_1) == 0) { 206 brelse(bh); 207 raw_inode = sysv_raw_inode(sb, ino, &bh); 208 if (!raw_inode) 209 goto Eio; 210 } else 211 raw_inode++; 212 } 213 brelse(bh); 214 if (count != sb_count) 215 goto Einval; 216 out: 217 mutex_unlock(&sbi->s_lock); 218 return count; 219 220 Einval: 221 printk("sysv_count_free_inodes: " 222 "free inode count was %d, correcting to %d\n", 223 sb_count, count); 224 if (!sb_rdonly(sb)) { 225 *sbi->s_sb_total_free_inodes = cpu_to_fs16(SYSV_SB(sb), count); 226 dirty_sb(sb); 227 } 228 goto out; 229 230 Eio: 231 printk("sysv_count_free_inodes: unable to read inode table\n"); 232 trust_sb: 233 count = sb_count; 234 goto out; 235 } 236
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.