Root/
1 | /* |
2 | * Copyright (c) 2000-2001 Christoph Hellwig. |
3 | * All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions, and the following disclaimer, |
10 | * without modification. |
11 | * 2. The name of the author may not be used to endorse or promote products |
12 | * derived from this software without specific prior written permission. |
13 | * |
14 | * Alternatively, this software may be distributed under the terms of the |
15 | * GNU General Public License ("GPL"). |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR |
21 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. |
28 | */ |
29 | |
30 | /* |
31 | * Veritas filesystem driver - inode routines. |
32 | */ |
33 | #include <linux/fs.h> |
34 | #include <linux/buffer_head.h> |
35 | #include <linux/pagemap.h> |
36 | #include <linux/kernel.h> |
37 | #include <linux/slab.h> |
38 | |
39 | #include "vxfs.h" |
40 | #include "vxfs_inode.h" |
41 | #include "vxfs_extern.h" |
42 | |
43 | |
44 | struct kmem_cache *vxfs_inode_cachep; |
45 | |
46 | |
47 | #ifdef DIAGNOSTIC |
48 | /* |
49 | * Dump inode contents (partially). |
50 | */ |
51 | void |
52 | vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) |
53 | { |
54 | printk(KERN_DEBUG "\n\n"); |
55 | if (ino) |
56 | printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino); |
57 | else |
58 | printk(KERN_DEBUG "dumping unknown vxfs inode\n"); |
59 | |
60 | printk(KERN_DEBUG "---------------------------\n"); |
61 | printk(KERN_DEBUG "mode is %x\n", vip->vii_mode); |
62 | printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n", |
63 | vip->vii_nlink, vip->vii_uid, vip->vii_gid); |
64 | printk(KERN_DEBUG "size:%Lx, blocks:%u\n", |
65 | vip->vii_size, vip->vii_blocks); |
66 | printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype); |
67 | } |
68 | #endif |
69 | |
70 | |
71 | /** |
72 | * vxfs_blkiget - find inode based on extent # |
73 | * @sbp: superblock of the filesystem we search in |
74 | * @extent: number of the extent to search |
75 | * @ino: inode number to search |
76 | * |
77 | * Description: |
78 | * vxfs_blkiget searches inode @ino in the filesystem described by |
79 | * @sbp in the extent @extent. |
80 | * Returns the matching VxFS inode on success, else a NULL pointer. |
81 | * |
82 | * NOTE: |
83 | * While __vxfs_iget uses the pagecache vxfs_blkiget uses the |
84 | * buffercache. This function should not be used outside the |
85 | * read_super() method, otherwise the data may be incoherent. |
86 | */ |
87 | struct vxfs_inode_info * |
88 | vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) |
89 | { |
90 | struct buffer_head *bp; |
91 | u_long block, offset; |
92 | |
93 | block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); |
94 | offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); |
95 | bp = sb_bread(sbp, block); |
96 | |
97 | if (bp && buffer_mapped(bp)) { |
98 | struct vxfs_inode_info *vip; |
99 | struct vxfs_dinode *dip; |
100 | |
101 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) |
102 | goto fail; |
103 | dip = (struct vxfs_dinode *)(bp->b_data + offset); |
104 | memcpy(vip, dip, sizeof(*vip)); |
105 | #ifdef DIAGNOSTIC |
106 | vxfs_dumpi(vip, ino); |
107 | #endif |
108 | brelse(bp); |
109 | return (vip); |
110 | } |
111 | |
112 | fail: |
113 | printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); |
114 | brelse(bp); |
115 | return NULL; |
116 | } |
117 | |
118 | /** |
119 | * __vxfs_iget - generic find inode facility |
120 | * @sbp: VFS superblock |
121 | * @ino: inode number |
122 | * @ilistp: inode list |
123 | * |
124 | * Description: |
125 | * Search the for inode number @ino in the filesystem |
126 | * described by @sbp. Use the specified inode table (@ilistp). |
127 | * Returns the matching VxFS inode on success, else an error code. |
128 | */ |
129 | static struct vxfs_inode_info * |
130 | __vxfs_iget(ino_t ino, struct inode *ilistp) |
131 | { |
132 | struct page *pp; |
133 | u_long offset; |
134 | |
135 | offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; |
136 | pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); |
137 | |
138 | if (!IS_ERR(pp)) { |
139 | struct vxfs_inode_info *vip; |
140 | struct vxfs_dinode *dip; |
141 | caddr_t kaddr = (char *)page_address(pp); |
142 | |
143 | if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) |
144 | goto fail; |
145 | dip = (struct vxfs_dinode *)(kaddr + offset); |
146 | memcpy(vip, dip, sizeof(*vip)); |
147 | #ifdef DIAGNOSTIC |
148 | vxfs_dumpi(vip, ino); |
149 | #endif |
150 | vxfs_put_page(pp); |
151 | return (vip); |
152 | } |
153 | |
154 | printk(KERN_WARNING "vxfs: error on page %p\n", pp); |
155 | return ERR_CAST(pp); |
156 | |
157 | fail: |
158 | printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); |
159 | vxfs_put_page(pp); |
160 | return ERR_PTR(-ENOMEM); |
161 | } |
162 | |
163 | /** |
164 | * vxfs_stiget - find inode using the structural inode list |
165 | * @sbp: VFS superblock |
166 | * @ino: inode # |
167 | * |
168 | * Description: |
169 | * Find inode @ino in the filesystem described by @sbp using |
170 | * the structural inode list. |
171 | * Returns the matching VxFS inode on success, else a NULL pointer. |
172 | */ |
173 | struct vxfs_inode_info * |
174 | vxfs_stiget(struct super_block *sbp, ino_t ino) |
175 | { |
176 | struct vxfs_inode_info *vip; |
177 | |
178 | vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); |
179 | return IS_ERR(vip) ? NULL : vip; |
180 | } |
181 | |
182 | /** |
183 | * vxfs_transmod - mode for a VxFS inode |
184 | * @vip: VxFS inode |
185 | * |
186 | * Description: |
187 | * vxfs_transmod returns a Linux mode_t for a given |
188 | * VxFS inode structure. |
189 | */ |
190 | static __inline__ mode_t |
191 | vxfs_transmod(struct vxfs_inode_info *vip) |
192 | { |
193 | mode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; |
194 | |
195 | if (VXFS_ISFIFO(vip)) |
196 | ret |= S_IFIFO; |
197 | if (VXFS_ISCHR(vip)) |
198 | ret |= S_IFCHR; |
199 | if (VXFS_ISDIR(vip)) |
200 | ret |= S_IFDIR; |
201 | if (VXFS_ISBLK(vip)) |
202 | ret |= S_IFBLK; |
203 | if (VXFS_ISLNK(vip)) |
204 | ret |= S_IFLNK; |
205 | if (VXFS_ISREG(vip)) |
206 | ret |= S_IFREG; |
207 | if (VXFS_ISSOC(vip)) |
208 | ret |= S_IFSOCK; |
209 | |
210 | return (ret); |
211 | } |
212 | |
213 | /** |
214 | * vxfs_iinit- helper to fill inode fields |
215 | * @ip: VFS inode |
216 | * @vip: VxFS inode |
217 | * |
218 | * Description: |
219 | * vxfs_instino is a helper function to fill in all relevant |
220 | * fields in @ip from @vip. |
221 | */ |
222 | static void |
223 | vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) |
224 | { |
225 | |
226 | ip->i_mode = vxfs_transmod(vip); |
227 | ip->i_uid = (uid_t)vip->vii_uid; |
228 | ip->i_gid = (gid_t)vip->vii_gid; |
229 | |
230 | ip->i_nlink = vip->vii_nlink; |
231 | ip->i_size = vip->vii_size; |
232 | |
233 | ip->i_atime.tv_sec = vip->vii_atime; |
234 | ip->i_ctime.tv_sec = vip->vii_ctime; |
235 | ip->i_mtime.tv_sec = vip->vii_mtime; |
236 | ip->i_atime.tv_nsec = 0; |
237 | ip->i_ctime.tv_nsec = 0; |
238 | ip->i_mtime.tv_nsec = 0; |
239 | |
240 | ip->i_blocks = vip->vii_blocks; |
241 | ip->i_generation = vip->vii_gen; |
242 | |
243 | ip->i_private = vip; |
244 | |
245 | } |
246 | |
247 | /** |
248 | * vxfs_get_fake_inode - get fake inode structure |
249 | * @sbp: filesystem superblock |
250 | * @vip: fspriv inode |
251 | * |
252 | * Description: |
253 | * vxfs_fake_inode gets a fake inode (not in the inode hash) for a |
254 | * superblock, vxfs_inode pair. |
255 | * Returns the filled VFS inode. |
256 | */ |
257 | struct inode * |
258 | vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) |
259 | { |
260 | struct inode *ip = NULL; |
261 | |
262 | if ((ip = new_inode(sbp))) { |
263 | vxfs_iinit(ip, vip); |
264 | ip->i_mapping->a_ops = &vxfs_aops; |
265 | } |
266 | return (ip); |
267 | } |
268 | |
269 | /** |
270 | * vxfs_put_fake_inode - free faked inode |
271 | * *ip: VFS inode |
272 | * |
273 | * Description: |
274 | * vxfs_put_fake_inode frees all data asssociated with @ip. |
275 | */ |
276 | void |
277 | vxfs_put_fake_inode(struct inode *ip) |
278 | { |
279 | iput(ip); |
280 | } |
281 | |
282 | /** |
283 | * vxfs_iget - get an inode |
284 | * @sbp: the superblock to get the inode for |
285 | * @ino: the number of the inode to get |
286 | * |
287 | * Description: |
288 | * vxfs_read_inode creates an inode, reads the disk inode for @ino and fills |
289 | * in all relevant fields in the new inode. |
290 | */ |
291 | struct inode * |
292 | vxfs_iget(struct super_block *sbp, ino_t ino) |
293 | { |
294 | struct vxfs_inode_info *vip; |
295 | const struct address_space_operations *aops; |
296 | struct inode *ip; |
297 | |
298 | ip = iget_locked(sbp, ino); |
299 | if (!ip) |
300 | return ERR_PTR(-ENOMEM); |
301 | if (!(ip->i_state & I_NEW)) |
302 | return ip; |
303 | |
304 | vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); |
305 | if (IS_ERR(vip)) { |
306 | iget_failed(ip); |
307 | return ERR_CAST(vip); |
308 | } |
309 | |
310 | vxfs_iinit(ip, vip); |
311 | |
312 | if (VXFS_ISIMMED(vip)) |
313 | aops = &vxfs_immed_aops; |
314 | else |
315 | aops = &vxfs_aops; |
316 | |
317 | if (S_ISREG(ip->i_mode)) { |
318 | ip->i_fop = &generic_ro_fops; |
319 | ip->i_mapping->a_ops = aops; |
320 | } else if (S_ISDIR(ip->i_mode)) { |
321 | ip->i_op = &vxfs_dir_inode_ops; |
322 | ip->i_fop = &vxfs_dir_operations; |
323 | ip->i_mapping->a_ops = aops; |
324 | } else if (S_ISLNK(ip->i_mode)) { |
325 | if (!VXFS_ISIMMED(vip)) { |
326 | ip->i_op = &page_symlink_inode_operations; |
327 | ip->i_mapping->a_ops = &vxfs_aops; |
328 | } else { |
329 | ip->i_op = &vxfs_immed_symlink_iops; |
330 | vip->vii_immed.vi_immed[ip->i_size] = '\0'; |
331 | } |
332 | } else |
333 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); |
334 | |
335 | unlock_new_inode(ip); |
336 | return ip; |
337 | } |
338 | |
339 | /** |
340 | * vxfs_clear_inode - remove inode from main memory |
341 | * @ip: inode to discard. |
342 | * |
343 | * Description: |
344 | * vxfs_clear_inode() is called on the final iput and frees the private |
345 | * inode area. |
346 | */ |
347 | void |
348 | vxfs_clear_inode(struct inode *ip) |
349 | { |
350 | kmem_cache_free(vxfs_inode_cachep, ip->i_private); |
351 | } |
352 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9