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: &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: i++) = cpu_to_fs16(sbi: SYSV_SB(sb), n: 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: &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: &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, n: *sbi->s_sb_fic_count); |
124 | if (count < sbi->s_fic_size) { |
125 | *sv_sb_fic_inode(sb,i: count++) = cpu_to_fs16(sbi, n: ino); |
126 | *sbi->s_sb_fic_count = cpu_to_fs16(sbi, n: count); |
127 | } |
128 | fs16_add(sbi, n: sbi->s_sb_total_free_inodes, d: 1); |
129 | dirty_sb(sb); |
130 | memset(raw_inode, 0, sizeof(struct sysv_inode)); |
131 | mark_buffer_dirty(bh); |
132 | mutex_unlock(lock: &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(error: -ENOMEM); |
150 | |
151 | mutex_lock(&sbi->s_lock); |
152 | count = fs16_to_cpu(sbi, n: *sbi->s_sb_fic_count); |
153 | if (count == 0 || (*sv_sb_fic_inode(sb,i: count-1) == 0)) { |
154 | count = refill_free_cache(sb); |
155 | if (count == 0) { |
156 | iput(inode); |
157 | mutex_unlock(lock: &sbi->s_lock); |
158 | return ERR_PTR(error: -ENOSPC); |
159 | } |
160 | } |
161 | /* Now count > 0. */ |
162 | ino = *sv_sb_fic_inode(sb,i: --count); |
163 | *sbi->s_sb_fic_count = cpu_to_fs16(sbi, n: count); |
164 | fs16_add(sbi, n: sbi->s_sb_total_free_inodes, d: -1); |
165 | dirty_sb(sb); |
166 | inode_init_owner(idmap: &nop_mnt_idmap, inode, dir, mode); |
167 | inode->i_ino = fs16_to_cpu(sbi, n: 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: &wbc); /* ensure inode not allocated again */ |
176 | mark_inode_dirty(inode); /* cleared by sysv_write_inode() */ |
177 | /* That's it. */ |
178 | mutex_unlock(lock: &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, n: *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: &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: &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(lock: &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(sbi: SYSV_SB(sb), n: 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 | |