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