1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * NILFS inode file |
4 | * |
5 | * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. |
6 | * |
7 | * Written by Amagai Yoshiji. |
8 | * Revised by Ryusuke Konishi. |
9 | * |
10 | */ |
11 | |
12 | #include <linux/types.h> |
13 | #include <linux/buffer_head.h> |
14 | #include "nilfs.h" |
15 | #include "mdt.h" |
16 | #include "alloc.h" |
17 | #include "ifile.h" |
18 | #include "cpfile.h" |
19 | |
20 | /** |
21 | * struct nilfs_ifile_info - on-memory private data of ifile |
22 | * @mi: on-memory private data of metadata file |
23 | * @palloc_cache: persistent object allocator cache of ifile |
24 | */ |
25 | struct nilfs_ifile_info { |
26 | struct nilfs_mdt_info mi; |
27 | struct nilfs_palloc_cache palloc_cache; |
28 | }; |
29 | |
30 | static inline struct nilfs_ifile_info *NILFS_IFILE_I(struct inode *ifile) |
31 | { |
32 | return (struct nilfs_ifile_info *)NILFS_MDT(inode: ifile); |
33 | } |
34 | |
35 | /** |
36 | * nilfs_ifile_create_inode - create a new disk inode |
37 | * @ifile: ifile inode |
38 | * @out_ino: pointer to a variable to store inode number |
39 | * @out_bh: buffer_head contains newly allocated disk inode |
40 | * |
41 | * Return Value: On success, 0 is returned and the newly allocated inode |
42 | * number is stored in the place pointed by @ino, and buffer_head pointer |
43 | * that contains newly allocated disk inode structure is stored in the |
44 | * place pointed by @out_bh |
45 | * On error, one of the following negative error codes is returned. |
46 | * |
47 | * %-EIO - I/O error. |
48 | * |
49 | * %-ENOMEM - Insufficient amount of memory available. |
50 | * |
51 | * %-ENOSPC - No inode left. |
52 | */ |
53 | int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino, |
54 | struct buffer_head **out_bh) |
55 | { |
56 | struct nilfs_palloc_req req; |
57 | int ret; |
58 | |
59 | req.pr_entry_nr = 0; /* |
60 | * 0 says find free inode from beginning |
61 | * of a group. dull code!! |
62 | */ |
63 | req.pr_entry_bh = NULL; |
64 | |
65 | ret = nilfs_palloc_prepare_alloc_entry(ifile, &req); |
66 | if (!ret) { |
67 | ret = nilfs_palloc_get_entry_block(ifile, req.pr_entry_nr, 1, |
68 | &req.pr_entry_bh); |
69 | if (ret < 0) |
70 | nilfs_palloc_abort_alloc_entry(ifile, &req); |
71 | } |
72 | if (ret < 0) { |
73 | brelse(bh: req.pr_entry_bh); |
74 | return ret; |
75 | } |
76 | nilfs_palloc_commit_alloc_entry(ifile, &req); |
77 | mark_buffer_dirty(bh: req.pr_entry_bh); |
78 | nilfs_mdt_mark_dirty(inode: ifile); |
79 | *out_ino = (ino_t)req.pr_entry_nr; |
80 | *out_bh = req.pr_entry_bh; |
81 | return 0; |
82 | } |
83 | |
84 | /** |
85 | * nilfs_ifile_delete_inode - delete a disk inode |
86 | * @ifile: ifile inode |
87 | * @ino: inode number |
88 | * |
89 | * Return Value: On success, 0 is returned. On error, one of the following |
90 | * negative error codes is returned. |
91 | * |
92 | * %-EIO - I/O error. |
93 | * |
94 | * %-ENOMEM - Insufficient amount of memory available. |
95 | * |
96 | * %-ENOENT - The inode number @ino have not been allocated. |
97 | */ |
98 | int nilfs_ifile_delete_inode(struct inode *ifile, ino_t ino) |
99 | { |
100 | struct nilfs_palloc_req req = { |
101 | .pr_entry_nr = ino, .pr_entry_bh = NULL |
102 | }; |
103 | struct nilfs_inode *raw_inode; |
104 | void *kaddr; |
105 | int ret; |
106 | |
107 | ret = nilfs_palloc_prepare_free_entry(ifile, &req); |
108 | if (!ret) { |
109 | ret = nilfs_palloc_get_entry_block(ifile, req.pr_entry_nr, 0, |
110 | &req.pr_entry_bh); |
111 | if (ret < 0) |
112 | nilfs_palloc_abort_free_entry(ifile, &req); |
113 | } |
114 | if (ret < 0) { |
115 | brelse(bh: req.pr_entry_bh); |
116 | return ret; |
117 | } |
118 | |
119 | kaddr = kmap_local_page(page: req.pr_entry_bh->b_page); |
120 | raw_inode = nilfs_palloc_block_get_entry(ifile, req.pr_entry_nr, |
121 | req.pr_entry_bh, kaddr); |
122 | raw_inode->i_flags = 0; |
123 | kunmap_local(kaddr); |
124 | |
125 | mark_buffer_dirty(bh: req.pr_entry_bh); |
126 | brelse(bh: req.pr_entry_bh); |
127 | |
128 | nilfs_palloc_commit_free_entry(ifile, &req); |
129 | |
130 | return 0; |
131 | } |
132 | |
133 | int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, |
134 | struct buffer_head **out_bh) |
135 | { |
136 | struct super_block *sb = ifile->i_sb; |
137 | int err; |
138 | |
139 | if (unlikely(!NILFS_VALID_INODE(sb, ino))) { |
140 | nilfs_error(sb, "bad inode number: %lu" , (unsigned long)ino); |
141 | return -EINVAL; |
142 | } |
143 | |
144 | err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); |
145 | if (unlikely(err)) |
146 | nilfs_warn(sb, "error %d reading inode: ino=%lu" , |
147 | err, (unsigned long)ino); |
148 | return err; |
149 | } |
150 | |
151 | /** |
152 | * nilfs_ifile_count_free_inodes - calculate free inodes count |
153 | * @ifile: ifile inode |
154 | * @nmaxinodes: current maximum of available inodes count [out] |
155 | * @nfreeinodes: free inodes count [out] |
156 | */ |
157 | int nilfs_ifile_count_free_inodes(struct inode *ifile, |
158 | u64 *nmaxinodes, u64 *nfreeinodes) |
159 | { |
160 | u64 nused; |
161 | int err; |
162 | |
163 | *nmaxinodes = 0; |
164 | *nfreeinodes = 0; |
165 | |
166 | nused = atomic64_read(v: &NILFS_I(inode: ifile)->i_root->inodes_count); |
167 | err = nilfs_palloc_count_max_entries(ifile, nused, nmaxinodes); |
168 | if (likely(!err)) |
169 | *nfreeinodes = *nmaxinodes - nused; |
170 | return err; |
171 | } |
172 | |
173 | /** |
174 | * nilfs_ifile_read - read or get ifile inode |
175 | * @sb: super block instance |
176 | * @root: root object |
177 | * @cno: number of checkpoint entry to read |
178 | * @inode_size: size of an inode |
179 | * |
180 | * Return: 0 on success, or the following negative error code on failure. |
181 | * * %-EINVAL - Invalid checkpoint. |
182 | * * %-ENOMEM - Insufficient memory available. |
183 | * * %-EIO - I/O error (including metadata corruption). |
184 | */ |
185 | int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root, |
186 | __u64 cno, size_t inode_size) |
187 | { |
188 | struct the_nilfs *nilfs; |
189 | struct inode *ifile; |
190 | int err; |
191 | |
192 | ifile = nilfs_iget_locked(sb, root, NILFS_IFILE_INO); |
193 | if (unlikely(!ifile)) |
194 | return -ENOMEM; |
195 | if (!(ifile->i_state & I_NEW)) |
196 | goto out; |
197 | |
198 | err = nilfs_mdt_init(inode: ifile, NILFS_MDT_GFP, |
199 | objsz: sizeof(struct nilfs_ifile_info)); |
200 | if (err) |
201 | goto failed; |
202 | |
203 | err = nilfs_palloc_init_blockgroup(ifile, inode_size); |
204 | if (err) |
205 | goto failed; |
206 | |
207 | nilfs_palloc_setup_cache(inode: ifile, cache: &NILFS_IFILE_I(ifile)->palloc_cache); |
208 | |
209 | nilfs = sb->s_fs_info; |
210 | err = nilfs_cpfile_read_checkpoint(cpfile: nilfs->ns_cpfile, cno, root, ifile); |
211 | if (err) |
212 | goto failed; |
213 | |
214 | unlock_new_inode(ifile); |
215 | out: |
216 | return 0; |
217 | failed: |
218 | iget_failed(ifile); |
219 | return err; |
220 | } |
221 | |