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