Commit bcd6d4ecf6868ed57d4daae5d48e52d0752566d2
Committed by
Linus Torvalds
1 parent
3542ae4c17
Exists in
master
and in
7 other branches
ufs: move non-layout parts of ufs_fs.h to fs/ufs/
Move prototypes and in-core structures to fs/ufs/ similar to what most other filesystems already do. I made little modifications: move also ufs debug macros and mount options constants into fs/ufs/ufs.h, this stuff also private for ufs. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 15 changed files with 171 additions and 198 deletions Inline Diff
fs/ufs/balloc.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/balloc.c | 2 | * linux/fs/ufs/balloc.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007 | 8 | * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007 |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/ufs_fs.h> | 12 | #include <linux/ufs_fs.h> |
13 | #include <linux/stat.h> | 13 | #include <linux/stat.h> |
14 | #include <linux/time.h> | 14 | #include <linux/time.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/quotaops.h> | 16 | #include <linux/quotaops.h> |
17 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
18 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
20 | #include <asm/byteorder.h> | 20 | #include <asm/byteorder.h> |
21 | 21 | ||
22 | #include "ufs.h" | ||
22 | #include "swab.h" | 23 | #include "swab.h" |
23 | #include "util.h" | 24 | #include "util.h" |
24 | 25 | ||
25 | #define INVBLOCK ((u64)-1L) | 26 | #define INVBLOCK ((u64)-1L) |
26 | 27 | ||
27 | static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *); | 28 | static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *); |
28 | static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *); | 29 | static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *); |
29 | static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *); | 30 | static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *); |
30 | static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned); | 31 | static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned); |
31 | static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; | 32 | static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[]; |
32 | static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); | 33 | static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int); |
33 | 34 | ||
34 | /* | 35 | /* |
35 | * Free 'count' fragments from fragment number 'fragment' | 36 | * Free 'count' fragments from fragment number 'fragment' |
36 | */ | 37 | */ |
37 | void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | 38 | void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) |
38 | { | 39 | { |
39 | struct super_block * sb; | 40 | struct super_block * sb; |
40 | struct ufs_sb_private_info * uspi; | 41 | struct ufs_sb_private_info * uspi; |
41 | struct ufs_super_block_first * usb1; | 42 | struct ufs_super_block_first * usb1; |
42 | struct ufs_cg_private_info * ucpi; | 43 | struct ufs_cg_private_info * ucpi; |
43 | struct ufs_cylinder_group * ucg; | 44 | struct ufs_cylinder_group * ucg; |
44 | unsigned cgno, bit, end_bit, bbase, blkmap, i; | 45 | unsigned cgno, bit, end_bit, bbase, blkmap, i; |
45 | u64 blkno; | 46 | u64 blkno; |
46 | 47 | ||
47 | sb = inode->i_sb; | 48 | sb = inode->i_sb; |
48 | uspi = UFS_SB(sb)->s_uspi; | 49 | uspi = UFS_SB(sb)->s_uspi; |
49 | usb1 = ubh_get_usb_first(uspi); | 50 | usb1 = ubh_get_usb_first(uspi); |
50 | 51 | ||
51 | UFSD("ENTER, fragment %llu, count %u\n", | 52 | UFSD("ENTER, fragment %llu, count %u\n", |
52 | (unsigned long long)fragment, count); | 53 | (unsigned long long)fragment, count); |
53 | 54 | ||
54 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) | 55 | if (ufs_fragnum(fragment) + count > uspi->s_fpg) |
55 | ufs_error (sb, "ufs_free_fragments", "internal error"); | 56 | ufs_error (sb, "ufs_free_fragments", "internal error"); |
56 | 57 | ||
57 | lock_super(sb); | 58 | lock_super(sb); |
58 | 59 | ||
59 | cgno = ufs_dtog(uspi, fragment); | 60 | cgno = ufs_dtog(uspi, fragment); |
60 | bit = ufs_dtogd(uspi, fragment); | 61 | bit = ufs_dtogd(uspi, fragment); |
61 | if (cgno >= uspi->s_ncg) { | 62 | if (cgno >= uspi->s_ncg) { |
62 | ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device"); | 63 | ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device"); |
63 | goto failed; | 64 | goto failed; |
64 | } | 65 | } |
65 | 66 | ||
66 | ucpi = ufs_load_cylinder (sb, cgno); | 67 | ucpi = ufs_load_cylinder (sb, cgno); |
67 | if (!ucpi) | 68 | if (!ucpi) |
68 | goto failed; | 69 | goto failed; |
69 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); | 70 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); |
70 | if (!ufs_cg_chkmagic(sb, ucg)) { | 71 | if (!ufs_cg_chkmagic(sb, ucg)) { |
71 | ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno); | 72 | ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno); |
72 | goto failed; | 73 | goto failed; |
73 | } | 74 | } |
74 | 75 | ||
75 | end_bit = bit + count; | 76 | end_bit = bit + count; |
76 | bbase = ufs_blknum (bit); | 77 | bbase = ufs_blknum (bit); |
77 | blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase); | 78 | blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase); |
78 | ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1); | 79 | ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1); |
79 | for (i = bit; i < end_bit; i++) { | 80 | for (i = bit; i < end_bit; i++) { |
80 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i)) | 81 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i)) |
81 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i); | 82 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i); |
82 | else | 83 | else |
83 | ufs_error (sb, "ufs_free_fragments", | 84 | ufs_error (sb, "ufs_free_fragments", |
84 | "bit already cleared for fragment %u", i); | 85 | "bit already cleared for fragment %u", i); |
85 | } | 86 | } |
86 | 87 | ||
87 | DQUOT_FREE_BLOCK (inode, count); | 88 | DQUOT_FREE_BLOCK (inode, count); |
88 | 89 | ||
89 | 90 | ||
90 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); | 91 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); |
91 | uspi->cs_total.cs_nffree += count; | 92 | uspi->cs_total.cs_nffree += count; |
92 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); | 93 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); |
93 | blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase); | 94 | blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase); |
94 | ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1); | 95 | ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1); |
95 | 96 | ||
96 | /* | 97 | /* |
97 | * Trying to reassemble free fragments into block | 98 | * Trying to reassemble free fragments into block |
98 | */ | 99 | */ |
99 | blkno = ufs_fragstoblks (bbase); | 100 | blkno = ufs_fragstoblks (bbase); |
100 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { | 101 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { |
101 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); | 102 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb); |
102 | uspi->cs_total.cs_nffree -= uspi->s_fpb; | 103 | uspi->cs_total.cs_nffree -= uspi->s_fpb; |
103 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); | 104 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb); |
104 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 105 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
105 | ufs_clusteracct (sb, ucpi, blkno, 1); | 106 | ufs_clusteracct (sb, ucpi, blkno, 1); |
106 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); | 107 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); |
107 | uspi->cs_total.cs_nbfree++; | 108 | uspi->cs_total.cs_nbfree++; |
108 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); | 109 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); |
109 | if (uspi->fs_magic != UFS2_MAGIC) { | 110 | if (uspi->fs_magic != UFS2_MAGIC) { |
110 | unsigned cylno = ufs_cbtocylno (bbase); | 111 | unsigned cylno = ufs_cbtocylno (bbase); |
111 | 112 | ||
112 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, | 113 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, |
113 | ufs_cbtorpos(bbase)), 1); | 114 | ufs_cbtorpos(bbase)), 1); |
114 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 115 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); |
115 | } | 116 | } |
116 | } | 117 | } |
117 | 118 | ||
118 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 119 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
119 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 120 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
120 | if (sb->s_flags & MS_SYNCHRONOUS) { | 121 | if (sb->s_flags & MS_SYNCHRONOUS) { |
121 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 122 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
122 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 123 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
123 | } | 124 | } |
124 | sb->s_dirt = 1; | 125 | sb->s_dirt = 1; |
125 | 126 | ||
126 | unlock_super (sb); | 127 | unlock_super (sb); |
127 | UFSD("EXIT\n"); | 128 | UFSD("EXIT\n"); |
128 | return; | 129 | return; |
129 | 130 | ||
130 | failed: | 131 | failed: |
131 | unlock_super (sb); | 132 | unlock_super (sb); |
132 | UFSD("EXIT (FAILED)\n"); | 133 | UFSD("EXIT (FAILED)\n"); |
133 | return; | 134 | return; |
134 | } | 135 | } |
135 | 136 | ||
136 | /* | 137 | /* |
137 | * Free 'count' fragments from fragment number 'fragment' (free whole blocks) | 138 | * Free 'count' fragments from fragment number 'fragment' (free whole blocks) |
138 | */ | 139 | */ |
139 | void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) | 140 | void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) |
140 | { | 141 | { |
141 | struct super_block * sb; | 142 | struct super_block * sb; |
142 | struct ufs_sb_private_info * uspi; | 143 | struct ufs_sb_private_info * uspi; |
143 | struct ufs_super_block_first * usb1; | 144 | struct ufs_super_block_first * usb1; |
144 | struct ufs_cg_private_info * ucpi; | 145 | struct ufs_cg_private_info * ucpi; |
145 | struct ufs_cylinder_group * ucg; | 146 | struct ufs_cylinder_group * ucg; |
146 | unsigned overflow, cgno, bit, end_bit, i; | 147 | unsigned overflow, cgno, bit, end_bit, i; |
147 | u64 blkno; | 148 | u64 blkno; |
148 | 149 | ||
149 | sb = inode->i_sb; | 150 | sb = inode->i_sb; |
150 | uspi = UFS_SB(sb)->s_uspi; | 151 | uspi = UFS_SB(sb)->s_uspi; |
151 | usb1 = ubh_get_usb_first(uspi); | 152 | usb1 = ubh_get_usb_first(uspi); |
152 | 153 | ||
153 | UFSD("ENTER, fragment %llu, count %u\n", | 154 | UFSD("ENTER, fragment %llu, count %u\n", |
154 | (unsigned long long)fragment, count); | 155 | (unsigned long long)fragment, count); |
155 | 156 | ||
156 | if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { | 157 | if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) { |
157 | ufs_error (sb, "ufs_free_blocks", "internal error, " | 158 | ufs_error (sb, "ufs_free_blocks", "internal error, " |
158 | "fragment %llu, count %u\n", | 159 | "fragment %llu, count %u\n", |
159 | (unsigned long long)fragment, count); | 160 | (unsigned long long)fragment, count); |
160 | goto failed; | 161 | goto failed; |
161 | } | 162 | } |
162 | 163 | ||
163 | lock_super(sb); | 164 | lock_super(sb); |
164 | 165 | ||
165 | do_more: | 166 | do_more: |
166 | overflow = 0; | 167 | overflow = 0; |
167 | cgno = ufs_dtog(uspi, fragment); | 168 | cgno = ufs_dtog(uspi, fragment); |
168 | bit = ufs_dtogd(uspi, fragment); | 169 | bit = ufs_dtogd(uspi, fragment); |
169 | if (cgno >= uspi->s_ncg) { | 170 | if (cgno >= uspi->s_ncg) { |
170 | ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device"); | 171 | ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device"); |
171 | goto failed_unlock; | 172 | goto failed_unlock; |
172 | } | 173 | } |
173 | end_bit = bit + count; | 174 | end_bit = bit + count; |
174 | if (end_bit > uspi->s_fpg) { | 175 | if (end_bit > uspi->s_fpg) { |
175 | overflow = bit + count - uspi->s_fpg; | 176 | overflow = bit + count - uspi->s_fpg; |
176 | count -= overflow; | 177 | count -= overflow; |
177 | end_bit -= overflow; | 178 | end_bit -= overflow; |
178 | } | 179 | } |
179 | 180 | ||
180 | ucpi = ufs_load_cylinder (sb, cgno); | 181 | ucpi = ufs_load_cylinder (sb, cgno); |
181 | if (!ucpi) | 182 | if (!ucpi) |
182 | goto failed_unlock; | 183 | goto failed_unlock; |
183 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); | 184 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); |
184 | if (!ufs_cg_chkmagic(sb, ucg)) { | 185 | if (!ufs_cg_chkmagic(sb, ucg)) { |
185 | ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno); | 186 | ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno); |
186 | goto failed_unlock; | 187 | goto failed_unlock; |
187 | } | 188 | } |
188 | 189 | ||
189 | for (i = bit; i < end_bit; i += uspi->s_fpb) { | 190 | for (i = bit; i < end_bit; i += uspi->s_fpb) { |
190 | blkno = ufs_fragstoblks(i); | 191 | blkno = ufs_fragstoblks(i); |
191 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { | 192 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) { |
192 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); | 193 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); |
193 | } | 194 | } |
194 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 195 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
195 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 196 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
196 | ufs_clusteracct (sb, ucpi, blkno, 1); | 197 | ufs_clusteracct (sb, ucpi, blkno, 1); |
197 | DQUOT_FREE_BLOCK(inode, uspi->s_fpb); | 198 | DQUOT_FREE_BLOCK(inode, uspi->s_fpb); |
198 | 199 | ||
199 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); | 200 | fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1); |
200 | uspi->cs_total.cs_nbfree++; | 201 | uspi->cs_total.cs_nbfree++; |
201 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); | 202 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1); |
202 | 203 | ||
203 | if (uspi->fs_magic != UFS2_MAGIC) { | 204 | if (uspi->fs_magic != UFS2_MAGIC) { |
204 | unsigned cylno = ufs_cbtocylno(i); | 205 | unsigned cylno = ufs_cbtocylno(i); |
205 | 206 | ||
206 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, | 207 | fs16_add(sb, &ubh_cg_blks(ucpi, cylno, |
207 | ufs_cbtorpos(i)), 1); | 208 | ufs_cbtorpos(i)), 1); |
208 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 209 | fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1); |
209 | } | 210 | } |
210 | } | 211 | } |
211 | 212 | ||
212 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 213 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
213 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 214 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
214 | if (sb->s_flags & MS_SYNCHRONOUS) { | 215 | if (sb->s_flags & MS_SYNCHRONOUS) { |
215 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 216 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
216 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 217 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
217 | } | 218 | } |
218 | 219 | ||
219 | if (overflow) { | 220 | if (overflow) { |
220 | fragment += count; | 221 | fragment += count; |
221 | count = overflow; | 222 | count = overflow; |
222 | goto do_more; | 223 | goto do_more; |
223 | } | 224 | } |
224 | 225 | ||
225 | sb->s_dirt = 1; | 226 | sb->s_dirt = 1; |
226 | unlock_super (sb); | 227 | unlock_super (sb); |
227 | UFSD("EXIT\n"); | 228 | UFSD("EXIT\n"); |
228 | return; | 229 | return; |
229 | 230 | ||
230 | failed_unlock: | 231 | failed_unlock: |
231 | unlock_super (sb); | 232 | unlock_super (sb); |
232 | failed: | 233 | failed: |
233 | UFSD("EXIT (FAILED)\n"); | 234 | UFSD("EXIT (FAILED)\n"); |
234 | return; | 235 | return; |
235 | } | 236 | } |
236 | 237 | ||
237 | /* | 238 | /* |
238 | * Modify inode page cache in such way: | 239 | * Modify inode page cache in such way: |
239 | * have - blocks with b_blocknr equal to oldb...oldb+count-1 | 240 | * have - blocks with b_blocknr equal to oldb...oldb+count-1 |
240 | * get - blocks with b_blocknr equal to newb...newb+count-1 | 241 | * get - blocks with b_blocknr equal to newb...newb+count-1 |
241 | * also we suppose that oldb...oldb+count-1 blocks | 242 | * also we suppose that oldb...oldb+count-1 blocks |
242 | * situated at the end of file. | 243 | * situated at the end of file. |
243 | * | 244 | * |
244 | * We can come here from ufs_writepage or ufs_prepare_write, | 245 | * We can come here from ufs_writepage or ufs_prepare_write, |
245 | * locked_page is argument of these functions, so we already lock it. | 246 | * locked_page is argument of these functions, so we already lock it. |
246 | */ | 247 | */ |
247 | static void ufs_change_blocknr(struct inode *inode, sector_t beg, | 248 | static void ufs_change_blocknr(struct inode *inode, sector_t beg, |
248 | unsigned int count, sector_t oldb, | 249 | unsigned int count, sector_t oldb, |
249 | sector_t newb, struct page *locked_page) | 250 | sector_t newb, struct page *locked_page) |
250 | { | 251 | { |
251 | const unsigned blks_per_page = | 252 | const unsigned blks_per_page = |
252 | 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 253 | 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
253 | const unsigned mask = blks_per_page - 1; | 254 | const unsigned mask = blks_per_page - 1; |
254 | struct address_space * const mapping = inode->i_mapping; | 255 | struct address_space * const mapping = inode->i_mapping; |
255 | pgoff_t index, cur_index, last_index; | 256 | pgoff_t index, cur_index, last_index; |
256 | unsigned pos, j, lblock; | 257 | unsigned pos, j, lblock; |
257 | sector_t end, i; | 258 | sector_t end, i; |
258 | struct page *page; | 259 | struct page *page; |
259 | struct buffer_head *head, *bh; | 260 | struct buffer_head *head, *bh; |
260 | 261 | ||
261 | UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n", | 262 | UFSD("ENTER, ino %lu, count %u, oldb %llu, newb %llu\n", |
262 | inode->i_ino, count, | 263 | inode->i_ino, count, |
263 | (unsigned long long)oldb, (unsigned long long)newb); | 264 | (unsigned long long)oldb, (unsigned long long)newb); |
264 | 265 | ||
265 | BUG_ON(!locked_page); | 266 | BUG_ON(!locked_page); |
266 | BUG_ON(!PageLocked(locked_page)); | 267 | BUG_ON(!PageLocked(locked_page)); |
267 | 268 | ||
268 | cur_index = locked_page->index; | 269 | cur_index = locked_page->index; |
269 | end = count + beg; | 270 | end = count + beg; |
270 | last_index = end >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 271 | last_index = end >> (PAGE_CACHE_SHIFT - inode->i_blkbits); |
271 | for (i = beg; i < end; i = (i | mask) + 1) { | 272 | for (i = beg; i < end; i = (i | mask) + 1) { |
272 | index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 273 | index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits); |
273 | 274 | ||
274 | if (likely(cur_index != index)) { | 275 | if (likely(cur_index != index)) { |
275 | page = ufs_get_locked_page(mapping, index); | 276 | page = ufs_get_locked_page(mapping, index); |
276 | if (!page)/* it was truncated */ | 277 | if (!page)/* it was truncated */ |
277 | continue; | 278 | continue; |
278 | if (IS_ERR(page)) {/* or EIO */ | 279 | if (IS_ERR(page)) {/* or EIO */ |
279 | ufs_error(inode->i_sb, __FUNCTION__, | 280 | ufs_error(inode->i_sb, __FUNCTION__, |
280 | "read of page %llu failed\n", | 281 | "read of page %llu failed\n", |
281 | (unsigned long long)index); | 282 | (unsigned long long)index); |
282 | continue; | 283 | continue; |
283 | } | 284 | } |
284 | } else | 285 | } else |
285 | page = locked_page; | 286 | page = locked_page; |
286 | 287 | ||
287 | head = page_buffers(page); | 288 | head = page_buffers(page); |
288 | bh = head; | 289 | bh = head; |
289 | pos = i & mask; | 290 | pos = i & mask; |
290 | for (j = 0; j < pos; ++j) | 291 | for (j = 0; j < pos; ++j) |
291 | bh = bh->b_this_page; | 292 | bh = bh->b_this_page; |
292 | 293 | ||
293 | 294 | ||
294 | if (unlikely(index == last_index)) | 295 | if (unlikely(index == last_index)) |
295 | lblock = end & mask; | 296 | lblock = end & mask; |
296 | else | 297 | else |
297 | lblock = blks_per_page; | 298 | lblock = blks_per_page; |
298 | 299 | ||
299 | do { | 300 | do { |
300 | if (j >= lblock) | 301 | if (j >= lblock) |
301 | break; | 302 | break; |
302 | pos = (i - beg) + j; | 303 | pos = (i - beg) + j; |
303 | 304 | ||
304 | if (!buffer_mapped(bh)) | 305 | if (!buffer_mapped(bh)) |
305 | map_bh(bh, inode->i_sb, oldb + pos); | 306 | map_bh(bh, inode->i_sb, oldb + pos); |
306 | if (!buffer_uptodate(bh)) { | 307 | if (!buffer_uptodate(bh)) { |
307 | ll_rw_block(READ, 1, &bh); | 308 | ll_rw_block(READ, 1, &bh); |
308 | wait_on_buffer(bh); | 309 | wait_on_buffer(bh); |
309 | if (!buffer_uptodate(bh)) { | 310 | if (!buffer_uptodate(bh)) { |
310 | ufs_error(inode->i_sb, __FUNCTION__, | 311 | ufs_error(inode->i_sb, __FUNCTION__, |
311 | "read of block failed\n"); | 312 | "read of block failed\n"); |
312 | break; | 313 | break; |
313 | } | 314 | } |
314 | } | 315 | } |
315 | 316 | ||
316 | UFSD(" change from %llu to %llu, pos %u\n", | 317 | UFSD(" change from %llu to %llu, pos %u\n", |
317 | (unsigned long long)pos + oldb, | 318 | (unsigned long long)pos + oldb, |
318 | (unsigned long long)pos + newb, pos); | 319 | (unsigned long long)pos + newb, pos); |
319 | 320 | ||
320 | bh->b_blocknr = newb + pos; | 321 | bh->b_blocknr = newb + pos; |
321 | unmap_underlying_metadata(bh->b_bdev, | 322 | unmap_underlying_metadata(bh->b_bdev, |
322 | bh->b_blocknr); | 323 | bh->b_blocknr); |
323 | mark_buffer_dirty(bh); | 324 | mark_buffer_dirty(bh); |
324 | ++j; | 325 | ++j; |
325 | bh = bh->b_this_page; | 326 | bh = bh->b_this_page; |
326 | } while (bh != head); | 327 | } while (bh != head); |
327 | 328 | ||
328 | if (likely(cur_index != index)) | 329 | if (likely(cur_index != index)) |
329 | ufs_put_locked_page(page); | 330 | ufs_put_locked_page(page); |
330 | } | 331 | } |
331 | UFSD("EXIT\n"); | 332 | UFSD("EXIT\n"); |
332 | } | 333 | } |
333 | 334 | ||
334 | static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n, | 335 | static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n, |
335 | int sync) | 336 | int sync) |
336 | { | 337 | { |
337 | struct buffer_head *bh; | 338 | struct buffer_head *bh; |
338 | sector_t end = beg + n; | 339 | sector_t end = beg + n; |
339 | 340 | ||
340 | for (; beg < end; ++beg) { | 341 | for (; beg < end; ++beg) { |
341 | bh = sb_getblk(inode->i_sb, beg); | 342 | bh = sb_getblk(inode->i_sb, beg); |
342 | lock_buffer(bh); | 343 | lock_buffer(bh); |
343 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); | 344 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); |
344 | set_buffer_uptodate(bh); | 345 | set_buffer_uptodate(bh); |
345 | mark_buffer_dirty(bh); | 346 | mark_buffer_dirty(bh); |
346 | unlock_buffer(bh); | 347 | unlock_buffer(bh); |
347 | if (IS_SYNC(inode) || sync) | 348 | if (IS_SYNC(inode) || sync) |
348 | sync_dirty_buffer(bh); | 349 | sync_dirty_buffer(bh); |
349 | brelse(bh); | 350 | brelse(bh); |
350 | } | 351 | } |
351 | } | 352 | } |
352 | 353 | ||
353 | u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | 354 | u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, |
354 | u64 goal, unsigned count, int *err, | 355 | u64 goal, unsigned count, int *err, |
355 | struct page *locked_page) | 356 | struct page *locked_page) |
356 | { | 357 | { |
357 | struct super_block * sb; | 358 | struct super_block * sb; |
358 | struct ufs_sb_private_info * uspi; | 359 | struct ufs_sb_private_info * uspi; |
359 | struct ufs_super_block_first * usb1; | 360 | struct ufs_super_block_first * usb1; |
360 | unsigned cgno, oldcount, newcount; | 361 | unsigned cgno, oldcount, newcount; |
361 | u64 tmp, request, result; | 362 | u64 tmp, request, result; |
362 | 363 | ||
363 | UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n", | 364 | UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n", |
364 | inode->i_ino, (unsigned long long)fragment, | 365 | inode->i_ino, (unsigned long long)fragment, |
365 | (unsigned long long)goal, count); | 366 | (unsigned long long)goal, count); |
366 | 367 | ||
367 | sb = inode->i_sb; | 368 | sb = inode->i_sb; |
368 | uspi = UFS_SB(sb)->s_uspi; | 369 | uspi = UFS_SB(sb)->s_uspi; |
369 | usb1 = ubh_get_usb_first(uspi); | 370 | usb1 = ubh_get_usb_first(uspi); |
370 | *err = -ENOSPC; | 371 | *err = -ENOSPC; |
371 | 372 | ||
372 | lock_super (sb); | 373 | lock_super (sb); |
373 | tmp = ufs_data_ptr_to_cpu(sb, p); | 374 | tmp = ufs_data_ptr_to_cpu(sb, p); |
374 | 375 | ||
375 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { | 376 | if (count + ufs_fragnum(fragment) > uspi->s_fpb) { |
376 | ufs_warning(sb, "ufs_new_fragments", "internal warning" | 377 | ufs_warning(sb, "ufs_new_fragments", "internal warning" |
377 | " fragment %llu, count %u", | 378 | " fragment %llu, count %u", |
378 | (unsigned long long)fragment, count); | 379 | (unsigned long long)fragment, count); |
379 | count = uspi->s_fpb - ufs_fragnum(fragment); | 380 | count = uspi->s_fpb - ufs_fragnum(fragment); |
380 | } | 381 | } |
381 | oldcount = ufs_fragnum (fragment); | 382 | oldcount = ufs_fragnum (fragment); |
382 | newcount = oldcount + count; | 383 | newcount = oldcount + count; |
383 | 384 | ||
384 | /* | 385 | /* |
385 | * Somebody else has just allocated our fragments | 386 | * Somebody else has just allocated our fragments |
386 | */ | 387 | */ |
387 | if (oldcount) { | 388 | if (oldcount) { |
388 | if (!tmp) { | 389 | if (!tmp) { |
389 | ufs_error(sb, "ufs_new_fragments", "internal error, " | 390 | ufs_error(sb, "ufs_new_fragments", "internal error, " |
390 | "fragment %llu, tmp %llu\n", | 391 | "fragment %llu, tmp %llu\n", |
391 | (unsigned long long)fragment, | 392 | (unsigned long long)fragment, |
392 | (unsigned long long)tmp); | 393 | (unsigned long long)tmp); |
393 | unlock_super(sb); | 394 | unlock_super(sb); |
394 | return INVBLOCK; | 395 | return INVBLOCK; |
395 | } | 396 | } |
396 | if (fragment < UFS_I(inode)->i_lastfrag) { | 397 | if (fragment < UFS_I(inode)->i_lastfrag) { |
397 | UFSD("EXIT (ALREADY ALLOCATED)\n"); | 398 | UFSD("EXIT (ALREADY ALLOCATED)\n"); |
398 | unlock_super (sb); | 399 | unlock_super (sb); |
399 | return 0; | 400 | return 0; |
400 | } | 401 | } |
401 | } | 402 | } |
402 | else { | 403 | else { |
403 | if (tmp) { | 404 | if (tmp) { |
404 | UFSD("EXIT (ALREADY ALLOCATED)\n"); | 405 | UFSD("EXIT (ALREADY ALLOCATED)\n"); |
405 | unlock_super(sb); | 406 | unlock_super(sb); |
406 | return 0; | 407 | return 0; |
407 | } | 408 | } |
408 | } | 409 | } |
409 | 410 | ||
410 | /* | 411 | /* |
411 | * There is not enough space for user on the device | 412 | * There is not enough space for user on the device |
412 | */ | 413 | */ |
413 | if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { | 414 | if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { |
414 | unlock_super (sb); | 415 | unlock_super (sb); |
415 | UFSD("EXIT (FAILED)\n"); | 416 | UFSD("EXIT (FAILED)\n"); |
416 | return 0; | 417 | return 0; |
417 | } | 418 | } |
418 | 419 | ||
419 | if (goal >= uspi->s_size) | 420 | if (goal >= uspi->s_size) |
420 | goal = 0; | 421 | goal = 0; |
421 | if (goal == 0) | 422 | if (goal == 0) |
422 | cgno = ufs_inotocg (inode->i_ino); | 423 | cgno = ufs_inotocg (inode->i_ino); |
423 | else | 424 | else |
424 | cgno = ufs_dtog(uspi, goal); | 425 | cgno = ufs_dtog(uspi, goal); |
425 | 426 | ||
426 | /* | 427 | /* |
427 | * allocate new fragment | 428 | * allocate new fragment |
428 | */ | 429 | */ |
429 | if (oldcount == 0) { | 430 | if (oldcount == 0) { |
430 | result = ufs_alloc_fragments (inode, cgno, goal, count, err); | 431 | result = ufs_alloc_fragments (inode, cgno, goal, count, err); |
431 | if (result) { | 432 | if (result) { |
432 | ufs_cpu_to_data_ptr(sb, p, result); | 433 | ufs_cpu_to_data_ptr(sb, p, result); |
433 | *err = 0; | 434 | *err = 0; |
434 | UFS_I(inode)->i_lastfrag = | 435 | UFS_I(inode)->i_lastfrag = |
435 | max_t(u32, UFS_I(inode)->i_lastfrag, | 436 | max_t(u32, UFS_I(inode)->i_lastfrag, |
436 | fragment + count); | 437 | fragment + count); |
437 | ufs_clear_frags(inode, result + oldcount, | 438 | ufs_clear_frags(inode, result + oldcount, |
438 | newcount - oldcount, locked_page != NULL); | 439 | newcount - oldcount, locked_page != NULL); |
439 | } | 440 | } |
440 | unlock_super(sb); | 441 | unlock_super(sb); |
441 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 442 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
442 | return result; | 443 | return result; |
443 | } | 444 | } |
444 | 445 | ||
445 | /* | 446 | /* |
446 | * resize block | 447 | * resize block |
447 | */ | 448 | */ |
448 | result = ufs_add_fragments (inode, tmp, oldcount, newcount, err); | 449 | result = ufs_add_fragments (inode, tmp, oldcount, newcount, err); |
449 | if (result) { | 450 | if (result) { |
450 | *err = 0; | 451 | *err = 0; |
451 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 452 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); |
452 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 453 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, |
453 | locked_page != NULL); | 454 | locked_page != NULL); |
454 | unlock_super(sb); | 455 | unlock_super(sb); |
455 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 456 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
456 | return result; | 457 | return result; |
457 | } | 458 | } |
458 | 459 | ||
459 | /* | 460 | /* |
460 | * allocate new block and move data | 461 | * allocate new block and move data |
461 | */ | 462 | */ |
462 | switch (fs32_to_cpu(sb, usb1->fs_optim)) { | 463 | switch (fs32_to_cpu(sb, usb1->fs_optim)) { |
463 | case UFS_OPTSPACE: | 464 | case UFS_OPTSPACE: |
464 | request = newcount; | 465 | request = newcount; |
465 | if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree | 466 | if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree |
466 | > uspi->s_dsize * uspi->s_minfree / (2 * 100)) | 467 | > uspi->s_dsize * uspi->s_minfree / (2 * 100)) |
467 | break; | 468 | break; |
468 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); | 469 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); |
469 | break; | 470 | break; |
470 | default: | 471 | default: |
471 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); | 472 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); |
472 | 473 | ||
473 | case UFS_OPTTIME: | 474 | case UFS_OPTTIME: |
474 | request = uspi->s_fpb; | 475 | request = uspi->s_fpb; |
475 | if (uspi->cs_total.cs_nffree < uspi->s_dsize * | 476 | if (uspi->cs_total.cs_nffree < uspi->s_dsize * |
476 | (uspi->s_minfree - 2) / 100) | 477 | (uspi->s_minfree - 2) / 100) |
477 | break; | 478 | break; |
478 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); | 479 | usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME); |
479 | break; | 480 | break; |
480 | } | 481 | } |
481 | result = ufs_alloc_fragments (inode, cgno, goal, request, err); | 482 | result = ufs_alloc_fragments (inode, cgno, goal, request, err); |
482 | if (result) { | 483 | if (result) { |
483 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | 484 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, |
484 | locked_page != NULL); | 485 | locked_page != NULL); |
485 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, | 486 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, |
486 | uspi->s_sbbase + tmp, | 487 | uspi->s_sbbase + tmp, |
487 | uspi->s_sbbase + result, locked_page); | 488 | uspi->s_sbbase + result, locked_page); |
488 | ufs_cpu_to_data_ptr(sb, p, result); | 489 | ufs_cpu_to_data_ptr(sb, p, result); |
489 | *err = 0; | 490 | *err = 0; |
490 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 491 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); |
491 | unlock_super(sb); | 492 | unlock_super(sb); |
492 | if (newcount < request) | 493 | if (newcount < request) |
493 | ufs_free_fragments (inode, result + newcount, request - newcount); | 494 | ufs_free_fragments (inode, result + newcount, request - newcount); |
494 | ufs_free_fragments (inode, tmp, oldcount); | 495 | ufs_free_fragments (inode, tmp, oldcount); |
495 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 496 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
496 | return result; | 497 | return result; |
497 | } | 498 | } |
498 | 499 | ||
499 | unlock_super(sb); | 500 | unlock_super(sb); |
500 | UFSD("EXIT (FAILED)\n"); | 501 | UFSD("EXIT (FAILED)\n"); |
501 | return 0; | 502 | return 0; |
502 | } | 503 | } |
503 | 504 | ||
504 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | 505 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, |
505 | unsigned oldcount, unsigned newcount, int *err) | 506 | unsigned oldcount, unsigned newcount, int *err) |
506 | { | 507 | { |
507 | struct super_block * sb; | 508 | struct super_block * sb; |
508 | struct ufs_sb_private_info * uspi; | 509 | struct ufs_sb_private_info * uspi; |
509 | struct ufs_super_block_first * usb1; | 510 | struct ufs_super_block_first * usb1; |
510 | struct ufs_cg_private_info * ucpi; | 511 | struct ufs_cg_private_info * ucpi; |
511 | struct ufs_cylinder_group * ucg; | 512 | struct ufs_cylinder_group * ucg; |
512 | unsigned cgno, fragno, fragoff, count, fragsize, i; | 513 | unsigned cgno, fragno, fragoff, count, fragsize, i; |
513 | 514 | ||
514 | UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n", | 515 | UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n", |
515 | (unsigned long long)fragment, oldcount, newcount); | 516 | (unsigned long long)fragment, oldcount, newcount); |
516 | 517 | ||
517 | sb = inode->i_sb; | 518 | sb = inode->i_sb; |
518 | uspi = UFS_SB(sb)->s_uspi; | 519 | uspi = UFS_SB(sb)->s_uspi; |
519 | usb1 = ubh_get_usb_first (uspi); | 520 | usb1 = ubh_get_usb_first (uspi); |
520 | count = newcount - oldcount; | 521 | count = newcount - oldcount; |
521 | 522 | ||
522 | cgno = ufs_dtog(uspi, fragment); | 523 | cgno = ufs_dtog(uspi, fragment); |
523 | if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count) | 524 | if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count) |
524 | return 0; | 525 | return 0; |
525 | if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb) | 526 | if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb) |
526 | return 0; | 527 | return 0; |
527 | ucpi = ufs_load_cylinder (sb, cgno); | 528 | ucpi = ufs_load_cylinder (sb, cgno); |
528 | if (!ucpi) | 529 | if (!ucpi) |
529 | return 0; | 530 | return 0; |
530 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); | 531 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); |
531 | if (!ufs_cg_chkmagic(sb, ucg)) { | 532 | if (!ufs_cg_chkmagic(sb, ucg)) { |
532 | ufs_panic (sb, "ufs_add_fragments", | 533 | ufs_panic (sb, "ufs_add_fragments", |
533 | "internal error, bad magic number on cg %u", cgno); | 534 | "internal error, bad magic number on cg %u", cgno); |
534 | return 0; | 535 | return 0; |
535 | } | 536 | } |
536 | 537 | ||
537 | fragno = ufs_dtogd(uspi, fragment); | 538 | fragno = ufs_dtogd(uspi, fragment); |
538 | fragoff = ufs_fragnum (fragno); | 539 | fragoff = ufs_fragnum (fragno); |
539 | for (i = oldcount; i < newcount; i++) | 540 | for (i = oldcount; i < newcount; i++) |
540 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) | 541 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) |
541 | return 0; | 542 | return 0; |
542 | /* | 543 | /* |
543 | * Block can be extended | 544 | * Block can be extended |
544 | */ | 545 | */ |
545 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); | 546 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); |
546 | for (i = newcount; i < (uspi->s_fpb - fragoff); i++) | 547 | for (i = newcount; i < (uspi->s_fpb - fragoff); i++) |
547 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) | 548 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) |
548 | break; | 549 | break; |
549 | fragsize = i - oldcount; | 550 | fragsize = i - oldcount; |
550 | if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize])) | 551 | if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize])) |
551 | ufs_panic (sb, "ufs_add_fragments", | 552 | ufs_panic (sb, "ufs_add_fragments", |
552 | "internal error or corrupted bitmap on cg %u", cgno); | 553 | "internal error or corrupted bitmap on cg %u", cgno); |
553 | fs32_sub(sb, &ucg->cg_frsum[fragsize], 1); | 554 | fs32_sub(sb, &ucg->cg_frsum[fragsize], 1); |
554 | if (fragsize != count) | 555 | if (fragsize != count) |
555 | fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1); | 556 | fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1); |
556 | for (i = oldcount; i < newcount; i++) | 557 | for (i = oldcount; i < newcount; i++) |
557 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i); | 558 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i); |
558 | if(DQUOT_ALLOC_BLOCK(inode, count)) { | 559 | if(DQUOT_ALLOC_BLOCK(inode, count)) { |
559 | *err = -EDQUOT; | 560 | *err = -EDQUOT; |
560 | return 0; | 561 | return 0; |
561 | } | 562 | } |
562 | 563 | ||
563 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, count); | 564 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, count); |
564 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); | 565 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); |
565 | uspi->cs_total.cs_nffree -= count; | 566 | uspi->cs_total.cs_nffree -= count; |
566 | 567 | ||
567 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 568 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
568 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 569 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
569 | if (sb->s_flags & MS_SYNCHRONOUS) { | 570 | if (sb->s_flags & MS_SYNCHRONOUS) { |
570 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 571 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
571 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 572 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
572 | } | 573 | } |
573 | sb->s_dirt = 1; | 574 | sb->s_dirt = 1; |
574 | 575 | ||
575 | UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); | 576 | UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); |
576 | 577 | ||
577 | return fragment; | 578 | return fragment; |
578 | } | 579 | } |
579 | 580 | ||
580 | #define UFS_TEST_FREE_SPACE_CG \ | 581 | #define UFS_TEST_FREE_SPACE_CG \ |
581 | ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \ | 582 | ucg = (struct ufs_cylinder_group *) UFS_SB(sb)->s_ucg[cgno]->b_data; \ |
582 | if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \ | 583 | if (fs32_to_cpu(sb, ucg->cg_cs.cs_nbfree)) \ |
583 | goto cg_found; \ | 584 | goto cg_found; \ |
584 | for (k = count; k < uspi->s_fpb; k++) \ | 585 | for (k = count; k < uspi->s_fpb; k++) \ |
585 | if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \ | 586 | if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \ |
586 | goto cg_found; | 587 | goto cg_found; |
587 | 588 | ||
588 | static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno, | 589 | static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno, |
589 | u64 goal, unsigned count, int *err) | 590 | u64 goal, unsigned count, int *err) |
590 | { | 591 | { |
591 | struct super_block * sb; | 592 | struct super_block * sb; |
592 | struct ufs_sb_private_info * uspi; | 593 | struct ufs_sb_private_info * uspi; |
593 | struct ufs_super_block_first * usb1; | 594 | struct ufs_super_block_first * usb1; |
594 | struct ufs_cg_private_info * ucpi; | 595 | struct ufs_cg_private_info * ucpi; |
595 | struct ufs_cylinder_group * ucg; | 596 | struct ufs_cylinder_group * ucg; |
596 | unsigned oldcg, i, j, k, allocsize; | 597 | unsigned oldcg, i, j, k, allocsize; |
597 | u64 result; | 598 | u64 result; |
598 | 599 | ||
599 | UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n", | 600 | UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n", |
600 | inode->i_ino, cgno, (unsigned long long)goal, count); | 601 | inode->i_ino, cgno, (unsigned long long)goal, count); |
601 | 602 | ||
602 | sb = inode->i_sb; | 603 | sb = inode->i_sb; |
603 | uspi = UFS_SB(sb)->s_uspi; | 604 | uspi = UFS_SB(sb)->s_uspi; |
604 | usb1 = ubh_get_usb_first(uspi); | 605 | usb1 = ubh_get_usb_first(uspi); |
605 | oldcg = cgno; | 606 | oldcg = cgno; |
606 | 607 | ||
607 | /* | 608 | /* |
608 | * 1. searching on preferred cylinder group | 609 | * 1. searching on preferred cylinder group |
609 | */ | 610 | */ |
610 | UFS_TEST_FREE_SPACE_CG | 611 | UFS_TEST_FREE_SPACE_CG |
611 | 612 | ||
612 | /* | 613 | /* |
613 | * 2. quadratic rehash | 614 | * 2. quadratic rehash |
614 | */ | 615 | */ |
615 | for (j = 1; j < uspi->s_ncg; j *= 2) { | 616 | for (j = 1; j < uspi->s_ncg; j *= 2) { |
616 | cgno += j; | 617 | cgno += j; |
617 | if (cgno >= uspi->s_ncg) | 618 | if (cgno >= uspi->s_ncg) |
618 | cgno -= uspi->s_ncg; | 619 | cgno -= uspi->s_ncg; |
619 | UFS_TEST_FREE_SPACE_CG | 620 | UFS_TEST_FREE_SPACE_CG |
620 | } | 621 | } |
621 | 622 | ||
622 | /* | 623 | /* |
623 | * 3. brute force search | 624 | * 3. brute force search |
624 | * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step ) | 625 | * We start at i = 2 ( 0 is checked at 1.step, 1 at 2.step ) |
625 | */ | 626 | */ |
626 | cgno = (oldcg + 1) % uspi->s_ncg; | 627 | cgno = (oldcg + 1) % uspi->s_ncg; |
627 | for (j = 2; j < uspi->s_ncg; j++) { | 628 | for (j = 2; j < uspi->s_ncg; j++) { |
628 | cgno++; | 629 | cgno++; |
629 | if (cgno >= uspi->s_ncg) | 630 | if (cgno >= uspi->s_ncg) |
630 | cgno = 0; | 631 | cgno = 0; |
631 | UFS_TEST_FREE_SPACE_CG | 632 | UFS_TEST_FREE_SPACE_CG |
632 | } | 633 | } |
633 | 634 | ||
634 | UFSD("EXIT (FAILED)\n"); | 635 | UFSD("EXIT (FAILED)\n"); |
635 | return 0; | 636 | return 0; |
636 | 637 | ||
637 | cg_found: | 638 | cg_found: |
638 | ucpi = ufs_load_cylinder (sb, cgno); | 639 | ucpi = ufs_load_cylinder (sb, cgno); |
639 | if (!ucpi) | 640 | if (!ucpi) |
640 | return 0; | 641 | return 0; |
641 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); | 642 | ucg = ubh_get_ucg (UCPI_UBH(ucpi)); |
642 | if (!ufs_cg_chkmagic(sb, ucg)) | 643 | if (!ufs_cg_chkmagic(sb, ucg)) |
643 | ufs_panic (sb, "ufs_alloc_fragments", | 644 | ufs_panic (sb, "ufs_alloc_fragments", |
644 | "internal error, bad magic number on cg %u", cgno); | 645 | "internal error, bad magic number on cg %u", cgno); |
645 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); | 646 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); |
646 | 647 | ||
647 | if (count == uspi->s_fpb) { | 648 | if (count == uspi->s_fpb) { |
648 | result = ufs_alloccg_block (inode, ucpi, goal, err); | 649 | result = ufs_alloccg_block (inode, ucpi, goal, err); |
649 | if (result == INVBLOCK) | 650 | if (result == INVBLOCK) |
650 | return 0; | 651 | return 0; |
651 | goto succed; | 652 | goto succed; |
652 | } | 653 | } |
653 | 654 | ||
654 | for (allocsize = count; allocsize < uspi->s_fpb; allocsize++) | 655 | for (allocsize = count; allocsize < uspi->s_fpb; allocsize++) |
655 | if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0) | 656 | if (fs32_to_cpu(sb, ucg->cg_frsum[allocsize]) != 0) |
656 | break; | 657 | break; |
657 | 658 | ||
658 | if (allocsize == uspi->s_fpb) { | 659 | if (allocsize == uspi->s_fpb) { |
659 | result = ufs_alloccg_block (inode, ucpi, goal, err); | 660 | result = ufs_alloccg_block (inode, ucpi, goal, err); |
660 | if (result == INVBLOCK) | 661 | if (result == INVBLOCK) |
661 | return 0; | 662 | return 0; |
662 | goal = ufs_dtogd(uspi, result); | 663 | goal = ufs_dtogd(uspi, result); |
663 | for (i = count; i < uspi->s_fpb; i++) | 664 | for (i = count; i < uspi->s_fpb; i++) |
664 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); | 665 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); |
665 | i = uspi->s_fpb - count; | 666 | i = uspi->s_fpb - count; |
666 | DQUOT_FREE_BLOCK(inode, i); | 667 | DQUOT_FREE_BLOCK(inode, i); |
667 | 668 | ||
668 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); | 669 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); |
669 | uspi->cs_total.cs_nffree += i; | 670 | uspi->cs_total.cs_nffree += i; |
670 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); | 671 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); |
671 | fs32_add(sb, &ucg->cg_frsum[i], 1); | 672 | fs32_add(sb, &ucg->cg_frsum[i], 1); |
672 | goto succed; | 673 | goto succed; |
673 | } | 674 | } |
674 | 675 | ||
675 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); | 676 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); |
676 | if (result == INVBLOCK) | 677 | if (result == INVBLOCK) |
677 | return 0; | 678 | return 0; |
678 | if(DQUOT_ALLOC_BLOCK(inode, count)) { | 679 | if(DQUOT_ALLOC_BLOCK(inode, count)) { |
679 | *err = -EDQUOT; | 680 | *err = -EDQUOT; |
680 | return 0; | 681 | return 0; |
681 | } | 682 | } |
682 | for (i = 0; i < count; i++) | 683 | for (i = 0; i < count; i++) |
683 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); | 684 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); |
684 | 685 | ||
685 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, count); | 686 | fs32_sub(sb, &ucg->cg_cs.cs_nffree, count); |
686 | uspi->cs_total.cs_nffree -= count; | 687 | uspi->cs_total.cs_nffree -= count; |
687 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); | 688 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); |
688 | fs32_sub(sb, &ucg->cg_frsum[allocsize], 1); | 689 | fs32_sub(sb, &ucg->cg_frsum[allocsize], 1); |
689 | 690 | ||
690 | if (count != allocsize) | 691 | if (count != allocsize) |
691 | fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1); | 692 | fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1); |
692 | 693 | ||
693 | succed: | 694 | succed: |
694 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 695 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
695 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 696 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
696 | if (sb->s_flags & MS_SYNCHRONOUS) { | 697 | if (sb->s_flags & MS_SYNCHRONOUS) { |
697 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 698 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
698 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 699 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
699 | } | 700 | } |
700 | sb->s_dirt = 1; | 701 | sb->s_dirt = 1; |
701 | 702 | ||
702 | result += cgno * uspi->s_fpg; | 703 | result += cgno * uspi->s_fpg; |
703 | UFSD("EXIT3, result %llu\n", (unsigned long long)result); | 704 | UFSD("EXIT3, result %llu\n", (unsigned long long)result); |
704 | return result; | 705 | return result; |
705 | } | 706 | } |
706 | 707 | ||
707 | static u64 ufs_alloccg_block(struct inode *inode, | 708 | static u64 ufs_alloccg_block(struct inode *inode, |
708 | struct ufs_cg_private_info *ucpi, | 709 | struct ufs_cg_private_info *ucpi, |
709 | u64 goal, int *err) | 710 | u64 goal, int *err) |
710 | { | 711 | { |
711 | struct super_block * sb; | 712 | struct super_block * sb; |
712 | struct ufs_sb_private_info * uspi; | 713 | struct ufs_sb_private_info * uspi; |
713 | struct ufs_super_block_first * usb1; | 714 | struct ufs_super_block_first * usb1; |
714 | struct ufs_cylinder_group * ucg; | 715 | struct ufs_cylinder_group * ucg; |
715 | u64 result, blkno; | 716 | u64 result, blkno; |
716 | 717 | ||
717 | UFSD("ENTER, goal %llu\n", (unsigned long long)goal); | 718 | UFSD("ENTER, goal %llu\n", (unsigned long long)goal); |
718 | 719 | ||
719 | sb = inode->i_sb; | 720 | sb = inode->i_sb; |
720 | uspi = UFS_SB(sb)->s_uspi; | 721 | uspi = UFS_SB(sb)->s_uspi; |
721 | usb1 = ubh_get_usb_first(uspi); | 722 | usb1 = ubh_get_usb_first(uspi); |
722 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 723 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
723 | 724 | ||
724 | if (goal == 0) { | 725 | if (goal == 0) { |
725 | goal = ucpi->c_rotor; | 726 | goal = ucpi->c_rotor; |
726 | goto norot; | 727 | goto norot; |
727 | } | 728 | } |
728 | goal = ufs_blknum (goal); | 729 | goal = ufs_blknum (goal); |
729 | goal = ufs_dtogd(uspi, goal); | 730 | goal = ufs_dtogd(uspi, goal); |
730 | 731 | ||
731 | /* | 732 | /* |
732 | * If the requested block is available, use it. | 733 | * If the requested block is available, use it. |
733 | */ | 734 | */ |
734 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) { | 735 | if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) { |
735 | result = goal; | 736 | result = goal; |
736 | goto gotit; | 737 | goto gotit; |
737 | } | 738 | } |
738 | 739 | ||
739 | norot: | 740 | norot: |
740 | result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); | 741 | result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb); |
741 | if (result == INVBLOCK) | 742 | if (result == INVBLOCK) |
742 | return INVBLOCK; | 743 | return INVBLOCK; |
743 | ucpi->c_rotor = result; | 744 | ucpi->c_rotor = result; |
744 | gotit: | 745 | gotit: |
745 | blkno = ufs_fragstoblks(result); | 746 | blkno = ufs_fragstoblks(result); |
746 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 747 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
747 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 748 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
748 | ufs_clusteracct (sb, ucpi, blkno, -1); | 749 | ufs_clusteracct (sb, ucpi, blkno, -1); |
749 | if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { | 750 | if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) { |
750 | *err = -EDQUOT; | 751 | *err = -EDQUOT; |
751 | return INVBLOCK; | 752 | return INVBLOCK; |
752 | } | 753 | } |
753 | 754 | ||
754 | fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); | 755 | fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1); |
755 | uspi->cs_total.cs_nbfree--; | 756 | uspi->cs_total.cs_nbfree--; |
756 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1); | 757 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1); |
757 | 758 | ||
758 | if (uspi->fs_magic != UFS2_MAGIC) { | 759 | if (uspi->fs_magic != UFS2_MAGIC) { |
759 | unsigned cylno = ufs_cbtocylno((unsigned)result); | 760 | unsigned cylno = ufs_cbtocylno((unsigned)result); |
760 | 761 | ||
761 | fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, | 762 | fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, |
762 | ufs_cbtorpos((unsigned)result)), 1); | 763 | ufs_cbtorpos((unsigned)result)), 1); |
763 | fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); | 764 | fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1); |
764 | } | 765 | } |
765 | 766 | ||
766 | UFSD("EXIT, result %llu\n", (unsigned long long)result); | 767 | UFSD("EXIT, result %llu\n", (unsigned long long)result); |
767 | 768 | ||
768 | return result; | 769 | return result; |
769 | } | 770 | } |
770 | 771 | ||
771 | static unsigned ubh_scanc(struct ufs_sb_private_info *uspi, | 772 | static unsigned ubh_scanc(struct ufs_sb_private_info *uspi, |
772 | struct ufs_buffer_head *ubh, | 773 | struct ufs_buffer_head *ubh, |
773 | unsigned begin, unsigned size, | 774 | unsigned begin, unsigned size, |
774 | unsigned char *table, unsigned char mask) | 775 | unsigned char *table, unsigned char mask) |
775 | { | 776 | { |
776 | unsigned rest, offset; | 777 | unsigned rest, offset; |
777 | unsigned char *cp; | 778 | unsigned char *cp; |
778 | 779 | ||
779 | 780 | ||
780 | offset = begin & ~uspi->s_fmask; | 781 | offset = begin & ~uspi->s_fmask; |
781 | begin >>= uspi->s_fshift; | 782 | begin >>= uspi->s_fshift; |
782 | for (;;) { | 783 | for (;;) { |
783 | if ((offset + size) < uspi->s_fsize) | 784 | if ((offset + size) < uspi->s_fsize) |
784 | rest = size; | 785 | rest = size; |
785 | else | 786 | else |
786 | rest = uspi->s_fsize - offset; | 787 | rest = uspi->s_fsize - offset; |
787 | size -= rest; | 788 | size -= rest; |
788 | cp = ubh->bh[begin]->b_data + offset; | 789 | cp = ubh->bh[begin]->b_data + offset; |
789 | while ((table[*cp++] & mask) == 0 && --rest) | 790 | while ((table[*cp++] & mask) == 0 && --rest) |
790 | ; | 791 | ; |
791 | if (rest || !size) | 792 | if (rest || !size) |
792 | break; | 793 | break; |
793 | begin++; | 794 | begin++; |
794 | offset = 0; | 795 | offset = 0; |
795 | } | 796 | } |
796 | return (size + rest); | 797 | return (size + rest); |
797 | } | 798 | } |
798 | 799 | ||
799 | /* | 800 | /* |
800 | * Find a block of the specified size in the specified cylinder group. | 801 | * Find a block of the specified size in the specified cylinder group. |
801 | * @sp: pointer to super block | 802 | * @sp: pointer to super block |
802 | * @ucpi: pointer to cylinder group info | 803 | * @ucpi: pointer to cylinder group info |
803 | * @goal: near which block we want find new one | 804 | * @goal: near which block we want find new one |
804 | * @count: specified size | 805 | * @count: specified size |
805 | */ | 806 | */ |
806 | static u64 ufs_bitmap_search(struct super_block *sb, | 807 | static u64 ufs_bitmap_search(struct super_block *sb, |
807 | struct ufs_cg_private_info *ucpi, | 808 | struct ufs_cg_private_info *ucpi, |
808 | u64 goal, unsigned count) | 809 | u64 goal, unsigned count) |
809 | { | 810 | { |
810 | /* | 811 | /* |
811 | * Bit patterns for identifying fragments in the block map | 812 | * Bit patterns for identifying fragments in the block map |
812 | * used as ((map & mask_arr) == want_arr) | 813 | * used as ((map & mask_arr) == want_arr) |
813 | */ | 814 | */ |
814 | static const int mask_arr[9] = { | 815 | static const int mask_arr[9] = { |
815 | 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff | 816 | 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff |
816 | }; | 817 | }; |
817 | static const int want_arr[9] = { | 818 | static const int want_arr[9] = { |
818 | 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe | 819 | 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe |
819 | }; | 820 | }; |
820 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 821 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
821 | struct ufs_super_block_first *usb1; | 822 | struct ufs_super_block_first *usb1; |
822 | struct ufs_cylinder_group *ucg; | 823 | struct ufs_cylinder_group *ucg; |
823 | unsigned start, length, loc; | 824 | unsigned start, length, loc; |
824 | unsigned pos, want, blockmap, mask, end; | 825 | unsigned pos, want, blockmap, mask, end; |
825 | u64 result; | 826 | u64 result; |
826 | 827 | ||
827 | UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx, | 828 | UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx, |
828 | (unsigned long long)goal, count); | 829 | (unsigned long long)goal, count); |
829 | 830 | ||
830 | usb1 = ubh_get_usb_first (uspi); | 831 | usb1 = ubh_get_usb_first (uspi); |
831 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 832 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
832 | 833 | ||
833 | if (goal) | 834 | if (goal) |
834 | start = ufs_dtogd(uspi, goal) >> 3; | 835 | start = ufs_dtogd(uspi, goal) >> 3; |
835 | else | 836 | else |
836 | start = ucpi->c_frotor >> 3; | 837 | start = ucpi->c_frotor >> 3; |
837 | 838 | ||
838 | length = ((uspi->s_fpg + 7) >> 3) - start; | 839 | length = ((uspi->s_fpg + 7) >> 3) - start; |
839 | loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length, | 840 | loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length, |
840 | (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, | 841 | (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, |
841 | 1 << (count - 1 + (uspi->s_fpb & 7))); | 842 | 1 << (count - 1 + (uspi->s_fpb & 7))); |
842 | if (loc == 0) { | 843 | if (loc == 0) { |
843 | length = start + 1; | 844 | length = start + 1; |
844 | loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length, | 845 | loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length, |
845 | (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : | 846 | (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : |
846 | ufs_fragtable_other, | 847 | ufs_fragtable_other, |
847 | 1 << (count - 1 + (uspi->s_fpb & 7))); | 848 | 1 << (count - 1 + (uspi->s_fpb & 7))); |
848 | if (loc == 0) { | 849 | if (loc == 0) { |
849 | ufs_error(sb, "ufs_bitmap_search", | 850 | ufs_error(sb, "ufs_bitmap_search", |
850 | "bitmap corrupted on cg %u, start %u," | 851 | "bitmap corrupted on cg %u, start %u," |
851 | " length %u, count %u, freeoff %u\n", | 852 | " length %u, count %u, freeoff %u\n", |
852 | ucpi->c_cgx, start, length, count, | 853 | ucpi->c_cgx, start, length, count, |
853 | ucpi->c_freeoff); | 854 | ucpi->c_freeoff); |
854 | return INVBLOCK; | 855 | return INVBLOCK; |
855 | } | 856 | } |
856 | start = 0; | 857 | start = 0; |
857 | } | 858 | } |
858 | result = (start + length - loc) << 3; | 859 | result = (start + length - loc) << 3; |
859 | ucpi->c_frotor = result; | 860 | ucpi->c_frotor = result; |
860 | 861 | ||
861 | /* | 862 | /* |
862 | * found the byte in the map | 863 | * found the byte in the map |
863 | */ | 864 | */ |
864 | 865 | ||
865 | for (end = result + 8; result < end; result += uspi->s_fpb) { | 866 | for (end = result + 8; result < end; result += uspi->s_fpb) { |
866 | blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result); | 867 | blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result); |
867 | blockmap <<= 1; | 868 | blockmap <<= 1; |
868 | mask = mask_arr[count]; | 869 | mask = mask_arr[count]; |
869 | want = want_arr[count]; | 870 | want = want_arr[count]; |
870 | for (pos = 0; pos <= uspi->s_fpb - count; pos++) { | 871 | for (pos = 0; pos <= uspi->s_fpb - count; pos++) { |
871 | if ((blockmap & mask) == want) { | 872 | if ((blockmap & mask) == want) { |
872 | UFSD("EXIT, result %llu\n", | 873 | UFSD("EXIT, result %llu\n", |
873 | (unsigned long long)result); | 874 | (unsigned long long)result); |
874 | return result + pos; | 875 | return result + pos; |
875 | } | 876 | } |
876 | mask <<= 1; | 877 | mask <<= 1; |
877 | want <<= 1; | 878 | want <<= 1; |
878 | } | 879 | } |
879 | } | 880 | } |
880 | 881 | ||
881 | ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n", | 882 | ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n", |
882 | ucpi->c_cgx); | 883 | ucpi->c_cgx); |
883 | UFSD("EXIT (FAILED)\n"); | 884 | UFSD("EXIT (FAILED)\n"); |
884 | return INVBLOCK; | 885 | return INVBLOCK; |
885 | } | 886 | } |
886 | 887 | ||
887 | static void ufs_clusteracct(struct super_block * sb, | 888 | static void ufs_clusteracct(struct super_block * sb, |
888 | struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt) | 889 | struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt) |
889 | { | 890 | { |
890 | struct ufs_sb_private_info * uspi; | 891 | struct ufs_sb_private_info * uspi; |
891 | int i, start, end, forw, back; | 892 | int i, start, end, forw, back; |
892 | 893 | ||
893 | uspi = UFS_SB(sb)->s_uspi; | 894 | uspi = UFS_SB(sb)->s_uspi; |
894 | if (uspi->s_contigsumsize <= 0) | 895 | if (uspi->s_contigsumsize <= 0) |
895 | return; | 896 | return; |
896 | 897 | ||
897 | if (cnt > 0) | 898 | if (cnt > 0) |
898 | ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno); | 899 | ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno); |
899 | else | 900 | else |
900 | ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno); | 901 | ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno); |
901 | 902 | ||
902 | /* | 903 | /* |
903 | * Find the size of the cluster going forward. | 904 | * Find the size of the cluster going forward. |
904 | */ | 905 | */ |
905 | start = blkno + 1; | 906 | start = blkno + 1; |
906 | end = start + uspi->s_contigsumsize; | 907 | end = start + uspi->s_contigsumsize; |
907 | if ( end >= ucpi->c_nclusterblks) | 908 | if ( end >= ucpi->c_nclusterblks) |
908 | end = ucpi->c_nclusterblks; | 909 | end = ucpi->c_nclusterblks; |
909 | i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start); | 910 | i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start); |
910 | if (i > end) | 911 | if (i > end) |
911 | i = end; | 912 | i = end; |
912 | forw = i - start; | 913 | forw = i - start; |
913 | 914 | ||
914 | /* | 915 | /* |
915 | * Find the size of the cluster going backward. | 916 | * Find the size of the cluster going backward. |
916 | */ | 917 | */ |
917 | start = blkno - 1; | 918 | start = blkno - 1; |
918 | end = start - uspi->s_contigsumsize; | 919 | end = start - uspi->s_contigsumsize; |
919 | if (end < 0 ) | 920 | if (end < 0 ) |
920 | end = -1; | 921 | end = -1; |
921 | i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end); | 922 | i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end); |
922 | if ( i < end) | 923 | if ( i < end) |
923 | i = end; | 924 | i = end; |
924 | back = start - i; | 925 | back = start - i; |
925 | 926 | ||
926 | /* | 927 | /* |
927 | * Account for old cluster and the possibly new forward and | 928 | * Account for old cluster and the possibly new forward and |
928 | * back clusters. | 929 | * back clusters. |
929 | */ | 930 | */ |
930 | i = back + forw + 1; | 931 | i = back + forw + 1; |
931 | if (i > uspi->s_contigsumsize) | 932 | if (i > uspi->s_contigsumsize) |
932 | i = uspi->s_contigsumsize; | 933 | i = uspi->s_contigsumsize; |
933 | fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt); | 934 | fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt); |
934 | if (back > 0) | 935 | if (back > 0) |
935 | fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt); | 936 | fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt); |
936 | if (forw > 0) | 937 | if (forw > 0) |
937 | fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt); | 938 | fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt); |
938 | } | 939 | } |
939 | 940 | ||
940 | 941 | ||
941 | static unsigned char ufs_fragtable_8fpb[] = { | 942 | static unsigned char ufs_fragtable_8fpb[] = { |
942 | 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, | 943 | 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, |
943 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, | 944 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10, |
944 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, | 945 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, |
945 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20, | 946 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20, |
946 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, | 947 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, |
947 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, | 948 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, |
948 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A, | 949 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A, |
949 | 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40, | 950 | 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x08, 0x09, 0x09, 0x0A, 0x10, 0x11, 0x20, 0x40, |
950 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, | 951 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, |
951 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, | 952 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11, |
952 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, | 953 | 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09, |
953 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21, | 954 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21, |
954 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A, | 955 | 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0A, |
955 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12, | 956 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0A, 0x12, |
956 | 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C, | 957 | 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0C, |
957 | 0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80, | 958 | 0x08, 0x09, 0x09, 0x0A, 0x09, 0x09, 0x0A, 0x0C, 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80, |
958 | }; | 959 | }; |
959 | 960 | ||
960 | static unsigned char ufs_fragtable_other[] = { | 961 | static unsigned char ufs_fragtable_other[] = { |
961 | 0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A, | 962 | 0x00, 0x16, 0x16, 0x2A, 0x16, 0x16, 0x26, 0x4E, 0x16, 0x16, 0x16, 0x3E, 0x2A, 0x3E, 0x4E, 0x8A, |
962 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 963 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
963 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 964 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
964 | 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA, | 965 | 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA, |
965 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 966 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
966 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 967 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
967 | 0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE, | 968 | 0x26, 0x36, 0x36, 0x2E, 0x36, 0x36, 0x26, 0x6E, 0x36, 0x36, 0x36, 0x3E, 0x2E, 0x3E, 0x6E, 0xAE, |
968 | 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE, | 969 | 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE, |
969 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 970 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
970 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 971 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
971 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, | 972 | 0x16, 0x16, 0x16, 0x3E, 0x16, 0x16, 0x36, 0x5E, 0x16, 0x16, 0x16, 0x3E, 0x3E, 0x3E, 0x5E, 0x9E, |
972 | 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE, | 973 | 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE, |
973 | 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA, | 974 | 0x2A, 0x3E, 0x3E, 0x2A, 0x3E, 0x3E, 0x2E, 0x6E, 0x3E, 0x3E, 0x3E, 0x3E, 0x2A, 0x3E, 0x6E, 0xAA, |
974 | 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE, | 975 | 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x7E, 0xBE, |
975 | 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE, | 976 | 0x4E, 0x5E, 0x5E, 0x6E, 0x5E, 0x5E, 0x6E, 0x4E, 0x5E, 0x5E, 0x5E, 0x7E, 0x6E, 0x7E, 0x4E, 0xCE, |
976 | 0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A, | 977 | 0x8A, 0x9E, 0x9E, 0xAA, 0x9E, 0x9E, 0xAE, 0xCE, 0x9E, 0x9E, 0x9E, 0xBE, 0xAA, 0xBE, 0xCE, 0x8A, |
977 | }; | 978 | }; |
978 | 979 |
fs/ufs/cylinder.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/cylinder.c | 2 | * linux/fs/ufs/cylinder.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * ext2 - inode (block) bitmap caching inspired | 8 | * ext2 - inode (block) bitmap caching inspired |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/ufs_fs.h> | 12 | #include <linux/ufs_fs.h> |
13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
17 | 17 | ||
18 | #include <asm/byteorder.h> | 18 | #include <asm/byteorder.h> |
19 | 19 | ||
20 | #include "ufs.h" | ||
20 | #include "swab.h" | 21 | #include "swab.h" |
21 | #include "util.h" | 22 | #include "util.h" |
22 | 23 | ||
23 | /* | 24 | /* |
24 | * Read cylinder group into cache. The memory space for ufs_cg_private_info | 25 | * Read cylinder group into cache. The memory space for ufs_cg_private_info |
25 | * structure is already allocated during ufs_read_super. | 26 | * structure is already allocated during ufs_read_super. |
26 | */ | 27 | */ |
27 | static void ufs_read_cylinder (struct super_block * sb, | 28 | static void ufs_read_cylinder (struct super_block * sb, |
28 | unsigned cgno, unsigned bitmap_nr) | 29 | unsigned cgno, unsigned bitmap_nr) |
29 | { | 30 | { |
30 | struct ufs_sb_info * sbi = UFS_SB(sb); | 31 | struct ufs_sb_info * sbi = UFS_SB(sb); |
31 | struct ufs_sb_private_info * uspi; | 32 | struct ufs_sb_private_info * uspi; |
32 | struct ufs_cg_private_info * ucpi; | 33 | struct ufs_cg_private_info * ucpi; |
33 | struct ufs_cylinder_group * ucg; | 34 | struct ufs_cylinder_group * ucg; |
34 | unsigned i, j; | 35 | unsigned i, j; |
35 | 36 | ||
36 | UFSD("ENTER, cgno %u, bitmap_nr %u\n", cgno, bitmap_nr); | 37 | UFSD("ENTER, cgno %u, bitmap_nr %u\n", cgno, bitmap_nr); |
37 | uspi = sbi->s_uspi; | 38 | uspi = sbi->s_uspi; |
38 | ucpi = sbi->s_ucpi[bitmap_nr]; | 39 | ucpi = sbi->s_ucpi[bitmap_nr]; |
39 | ucg = (struct ufs_cylinder_group *)sbi->s_ucg[cgno]->b_data; | 40 | ucg = (struct ufs_cylinder_group *)sbi->s_ucg[cgno]->b_data; |
40 | 41 | ||
41 | UCPI_UBH(ucpi)->fragment = ufs_cgcmin(cgno); | 42 | UCPI_UBH(ucpi)->fragment = ufs_cgcmin(cgno); |
42 | UCPI_UBH(ucpi)->count = uspi->s_cgsize >> sb->s_blocksize_bits; | 43 | UCPI_UBH(ucpi)->count = uspi->s_cgsize >> sb->s_blocksize_bits; |
43 | /* | 44 | /* |
44 | * We have already the first fragment of cylinder group block in buffer | 45 | * We have already the first fragment of cylinder group block in buffer |
45 | */ | 46 | */ |
46 | UCPI_UBH(ucpi)->bh[0] = sbi->s_ucg[cgno]; | 47 | UCPI_UBH(ucpi)->bh[0] = sbi->s_ucg[cgno]; |
47 | for (i = 1; i < UCPI_UBH(ucpi)->count; i++) | 48 | for (i = 1; i < UCPI_UBH(ucpi)->count; i++) |
48 | if (!(UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i))) | 49 | if (!(UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i))) |
49 | goto failed; | 50 | goto failed; |
50 | sbi->s_cgno[bitmap_nr] = cgno; | 51 | sbi->s_cgno[bitmap_nr] = cgno; |
51 | 52 | ||
52 | ucpi->c_cgx = fs32_to_cpu(sb, ucg->cg_cgx); | 53 | ucpi->c_cgx = fs32_to_cpu(sb, ucg->cg_cgx); |
53 | ucpi->c_ncyl = fs16_to_cpu(sb, ucg->cg_ncyl); | 54 | ucpi->c_ncyl = fs16_to_cpu(sb, ucg->cg_ncyl); |
54 | ucpi->c_niblk = fs16_to_cpu(sb, ucg->cg_niblk); | 55 | ucpi->c_niblk = fs16_to_cpu(sb, ucg->cg_niblk); |
55 | ucpi->c_ndblk = fs32_to_cpu(sb, ucg->cg_ndblk); | 56 | ucpi->c_ndblk = fs32_to_cpu(sb, ucg->cg_ndblk); |
56 | ucpi->c_rotor = fs32_to_cpu(sb, ucg->cg_rotor); | 57 | ucpi->c_rotor = fs32_to_cpu(sb, ucg->cg_rotor); |
57 | ucpi->c_frotor = fs32_to_cpu(sb, ucg->cg_frotor); | 58 | ucpi->c_frotor = fs32_to_cpu(sb, ucg->cg_frotor); |
58 | ucpi->c_irotor = fs32_to_cpu(sb, ucg->cg_irotor); | 59 | ucpi->c_irotor = fs32_to_cpu(sb, ucg->cg_irotor); |
59 | ucpi->c_btotoff = fs32_to_cpu(sb, ucg->cg_btotoff); | 60 | ucpi->c_btotoff = fs32_to_cpu(sb, ucg->cg_btotoff); |
60 | ucpi->c_boff = fs32_to_cpu(sb, ucg->cg_boff); | 61 | ucpi->c_boff = fs32_to_cpu(sb, ucg->cg_boff); |
61 | ucpi->c_iusedoff = fs32_to_cpu(sb, ucg->cg_iusedoff); | 62 | ucpi->c_iusedoff = fs32_to_cpu(sb, ucg->cg_iusedoff); |
62 | ucpi->c_freeoff = fs32_to_cpu(sb, ucg->cg_freeoff); | 63 | ucpi->c_freeoff = fs32_to_cpu(sb, ucg->cg_freeoff); |
63 | ucpi->c_nextfreeoff = fs32_to_cpu(sb, ucg->cg_nextfreeoff); | 64 | ucpi->c_nextfreeoff = fs32_to_cpu(sb, ucg->cg_nextfreeoff); |
64 | ucpi->c_clustersumoff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clustersumoff); | 65 | ucpi->c_clustersumoff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clustersumoff); |
65 | ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff); | 66 | ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff); |
66 | ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks); | 67 | ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks); |
67 | UFSD("EXIT\n"); | 68 | UFSD("EXIT\n"); |
68 | return; | 69 | return; |
69 | 70 | ||
70 | failed: | 71 | failed: |
71 | for (j = 1; j < i; j++) | 72 | for (j = 1; j < i; j++) |
72 | brelse (sbi->s_ucg[j]); | 73 | brelse (sbi->s_ucg[j]); |
73 | sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY; | 74 | sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY; |
74 | ufs_error (sb, "ufs_read_cylinder", "can't read cylinder group block %u", cgno); | 75 | ufs_error (sb, "ufs_read_cylinder", "can't read cylinder group block %u", cgno); |
75 | } | 76 | } |
76 | 77 | ||
77 | /* | 78 | /* |
78 | * Remove cylinder group from cache, doesn't release memory | 79 | * Remove cylinder group from cache, doesn't release memory |
79 | * allocated for cylinder group (this is done at ufs_put_super only). | 80 | * allocated for cylinder group (this is done at ufs_put_super only). |
80 | */ | 81 | */ |
81 | void ufs_put_cylinder (struct super_block * sb, unsigned bitmap_nr) | 82 | void ufs_put_cylinder (struct super_block * sb, unsigned bitmap_nr) |
82 | { | 83 | { |
83 | struct ufs_sb_info * sbi = UFS_SB(sb); | 84 | struct ufs_sb_info * sbi = UFS_SB(sb); |
84 | struct ufs_sb_private_info * uspi; | 85 | struct ufs_sb_private_info * uspi; |
85 | struct ufs_cg_private_info * ucpi; | 86 | struct ufs_cg_private_info * ucpi; |
86 | struct ufs_cylinder_group * ucg; | 87 | struct ufs_cylinder_group * ucg; |
87 | unsigned i; | 88 | unsigned i; |
88 | 89 | ||
89 | UFSD("ENTER, bitmap_nr %u\n", bitmap_nr); | 90 | UFSD("ENTER, bitmap_nr %u\n", bitmap_nr); |
90 | 91 | ||
91 | uspi = sbi->s_uspi; | 92 | uspi = sbi->s_uspi; |
92 | if (sbi->s_cgno[bitmap_nr] == UFS_CGNO_EMPTY) { | 93 | if (sbi->s_cgno[bitmap_nr] == UFS_CGNO_EMPTY) { |
93 | UFSD("EXIT\n"); | 94 | UFSD("EXIT\n"); |
94 | return; | 95 | return; |
95 | } | 96 | } |
96 | ucpi = sbi->s_ucpi[bitmap_nr]; | 97 | ucpi = sbi->s_ucpi[bitmap_nr]; |
97 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 98 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
98 | 99 | ||
99 | if (uspi->s_ncg > UFS_MAX_GROUP_LOADED && bitmap_nr >= sbi->s_cg_loaded) { | 100 | if (uspi->s_ncg > UFS_MAX_GROUP_LOADED && bitmap_nr >= sbi->s_cg_loaded) { |
100 | ufs_panic (sb, "ufs_put_cylinder", "internal error"); | 101 | ufs_panic (sb, "ufs_put_cylinder", "internal error"); |
101 | return; | 102 | return; |
102 | } | 103 | } |
103 | /* | 104 | /* |
104 | * rotor is not so important data, so we put it to disk | 105 | * rotor is not so important data, so we put it to disk |
105 | * at the end of working with cylinder | 106 | * at the end of working with cylinder |
106 | */ | 107 | */ |
107 | ucg->cg_rotor = cpu_to_fs32(sb, ucpi->c_rotor); | 108 | ucg->cg_rotor = cpu_to_fs32(sb, ucpi->c_rotor); |
108 | ucg->cg_frotor = cpu_to_fs32(sb, ucpi->c_frotor); | 109 | ucg->cg_frotor = cpu_to_fs32(sb, ucpi->c_frotor); |
109 | ucg->cg_irotor = cpu_to_fs32(sb, ucpi->c_irotor); | 110 | ucg->cg_irotor = cpu_to_fs32(sb, ucpi->c_irotor); |
110 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 111 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
111 | for (i = 1; i < UCPI_UBH(ucpi)->count; i++) { | 112 | for (i = 1; i < UCPI_UBH(ucpi)->count; i++) { |
112 | brelse (UCPI_UBH(ucpi)->bh[i]); | 113 | brelse (UCPI_UBH(ucpi)->bh[i]); |
113 | } | 114 | } |
114 | 115 | ||
115 | sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY; | 116 | sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY; |
116 | UFSD("EXIT\n"); | 117 | UFSD("EXIT\n"); |
117 | } | 118 | } |
118 | 119 | ||
119 | /* | 120 | /* |
120 | * Find cylinder group in cache and return it as pointer. | 121 | * Find cylinder group in cache and return it as pointer. |
121 | * If cylinder group is not in cache, we will load it from disk. | 122 | * If cylinder group is not in cache, we will load it from disk. |
122 | * | 123 | * |
123 | * The cache is managed by LRU algorithm. | 124 | * The cache is managed by LRU algorithm. |
124 | */ | 125 | */ |
125 | struct ufs_cg_private_info * ufs_load_cylinder ( | 126 | struct ufs_cg_private_info * ufs_load_cylinder ( |
126 | struct super_block * sb, unsigned cgno) | 127 | struct super_block * sb, unsigned cgno) |
127 | { | 128 | { |
128 | struct ufs_sb_info * sbi = UFS_SB(sb); | 129 | struct ufs_sb_info * sbi = UFS_SB(sb); |
129 | struct ufs_sb_private_info * uspi; | 130 | struct ufs_sb_private_info * uspi; |
130 | struct ufs_cg_private_info * ucpi; | 131 | struct ufs_cg_private_info * ucpi; |
131 | unsigned cg, i, j; | 132 | unsigned cg, i, j; |
132 | 133 | ||
133 | UFSD("ENTER, cgno %u\n", cgno); | 134 | UFSD("ENTER, cgno %u\n", cgno); |
134 | 135 | ||
135 | uspi = sbi->s_uspi; | 136 | uspi = sbi->s_uspi; |
136 | if (cgno >= uspi->s_ncg) { | 137 | if (cgno >= uspi->s_ncg) { |
137 | ufs_panic (sb, "ufs_load_cylinder", "internal error, high number of cg"); | 138 | ufs_panic (sb, "ufs_load_cylinder", "internal error, high number of cg"); |
138 | return NULL; | 139 | return NULL; |
139 | } | 140 | } |
140 | /* | 141 | /* |
141 | * Cylinder group number cg it in cache and it was last used | 142 | * Cylinder group number cg it in cache and it was last used |
142 | */ | 143 | */ |
143 | if (sbi->s_cgno[0] == cgno) { | 144 | if (sbi->s_cgno[0] == cgno) { |
144 | UFSD("EXIT\n"); | 145 | UFSD("EXIT\n"); |
145 | return sbi->s_ucpi[0]; | 146 | return sbi->s_ucpi[0]; |
146 | } | 147 | } |
147 | /* | 148 | /* |
148 | * Number of cylinder groups is not higher than UFS_MAX_GROUP_LOADED | 149 | * Number of cylinder groups is not higher than UFS_MAX_GROUP_LOADED |
149 | */ | 150 | */ |
150 | if (uspi->s_ncg <= UFS_MAX_GROUP_LOADED) { | 151 | if (uspi->s_ncg <= UFS_MAX_GROUP_LOADED) { |
151 | if (sbi->s_cgno[cgno] != UFS_CGNO_EMPTY) { | 152 | if (sbi->s_cgno[cgno] != UFS_CGNO_EMPTY) { |
152 | if (sbi->s_cgno[cgno] != cgno) { | 153 | if (sbi->s_cgno[cgno] != cgno) { |
153 | ufs_panic (sb, "ufs_load_cylinder", "internal error, wrong number of cg in cache"); | 154 | ufs_panic (sb, "ufs_load_cylinder", "internal error, wrong number of cg in cache"); |
154 | UFSD("EXIT (FAILED)\n"); | 155 | UFSD("EXIT (FAILED)\n"); |
155 | return NULL; | 156 | return NULL; |
156 | } | 157 | } |
157 | else { | 158 | else { |
158 | UFSD("EXIT\n"); | 159 | UFSD("EXIT\n"); |
159 | return sbi->s_ucpi[cgno]; | 160 | return sbi->s_ucpi[cgno]; |
160 | } | 161 | } |
161 | } else { | 162 | } else { |
162 | ufs_read_cylinder (sb, cgno, cgno); | 163 | ufs_read_cylinder (sb, cgno, cgno); |
163 | UFSD("EXIT\n"); | 164 | UFSD("EXIT\n"); |
164 | return sbi->s_ucpi[cgno]; | 165 | return sbi->s_ucpi[cgno]; |
165 | } | 166 | } |
166 | } | 167 | } |
167 | /* | 168 | /* |
168 | * Cylinder group number cg is in cache but it was not last used, | 169 | * Cylinder group number cg is in cache but it was not last used, |
169 | * we will move to the first position | 170 | * we will move to the first position |
170 | */ | 171 | */ |
171 | for (i = 0; i < sbi->s_cg_loaded && sbi->s_cgno[i] != cgno; i++); | 172 | for (i = 0; i < sbi->s_cg_loaded && sbi->s_cgno[i] != cgno; i++); |
172 | if (i < sbi->s_cg_loaded && sbi->s_cgno[i] == cgno) { | 173 | if (i < sbi->s_cg_loaded && sbi->s_cgno[i] == cgno) { |
173 | cg = sbi->s_cgno[i]; | 174 | cg = sbi->s_cgno[i]; |
174 | ucpi = sbi->s_ucpi[i]; | 175 | ucpi = sbi->s_ucpi[i]; |
175 | for (j = i; j > 0; j--) { | 176 | for (j = i; j > 0; j--) { |
176 | sbi->s_cgno[j] = sbi->s_cgno[j-1]; | 177 | sbi->s_cgno[j] = sbi->s_cgno[j-1]; |
177 | sbi->s_ucpi[j] = sbi->s_ucpi[j-1]; | 178 | sbi->s_ucpi[j] = sbi->s_ucpi[j-1]; |
178 | } | 179 | } |
179 | sbi->s_cgno[0] = cg; | 180 | sbi->s_cgno[0] = cg; |
180 | sbi->s_ucpi[0] = ucpi; | 181 | sbi->s_ucpi[0] = ucpi; |
181 | /* | 182 | /* |
182 | * Cylinder group number cg is not in cache, we will read it from disk | 183 | * Cylinder group number cg is not in cache, we will read it from disk |
183 | * and put it to the first position | 184 | * and put it to the first position |
184 | */ | 185 | */ |
185 | } else { | 186 | } else { |
186 | if (sbi->s_cg_loaded < UFS_MAX_GROUP_LOADED) | 187 | if (sbi->s_cg_loaded < UFS_MAX_GROUP_LOADED) |
187 | sbi->s_cg_loaded++; | 188 | sbi->s_cg_loaded++; |
188 | else | 189 | else |
189 | ufs_put_cylinder (sb, UFS_MAX_GROUP_LOADED-1); | 190 | ufs_put_cylinder (sb, UFS_MAX_GROUP_LOADED-1); |
190 | ucpi = sbi->s_ucpi[sbi->s_cg_loaded - 1]; | 191 | ucpi = sbi->s_ucpi[sbi->s_cg_loaded - 1]; |
191 | for (j = sbi->s_cg_loaded - 1; j > 0; j--) { | 192 | for (j = sbi->s_cg_loaded - 1; j > 0; j--) { |
192 | sbi->s_cgno[j] = sbi->s_cgno[j-1]; | 193 | sbi->s_cgno[j] = sbi->s_cgno[j-1]; |
193 | sbi->s_ucpi[j] = sbi->s_ucpi[j-1]; | 194 | sbi->s_ucpi[j] = sbi->s_ucpi[j-1]; |
194 | } | 195 | } |
195 | sbi->s_ucpi[0] = ucpi; | 196 | sbi->s_ucpi[0] = ucpi; |
196 | ufs_read_cylinder (sb, cgno, 0); | 197 | ufs_read_cylinder (sb, cgno, 0); |
197 | } | 198 | } |
198 | UFSD("EXIT\n"); | 199 | UFSD("EXIT\n"); |
199 | return sbi->s_ucpi[0]; | 200 | return sbi->s_ucpi[0]; |
200 | } | 201 | } |
201 | 202 |
fs/ufs/dir.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/ufs_dir.c | 2 | * linux/fs/ufs/ufs_dir.c |
3 | * | 3 | * |
4 | * Copyright (C) 1996 | 4 | * Copyright (C) 1996 |
5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) | 5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) |
6 | * Laboratory for Computer Science Research Computing Facility | 6 | * Laboratory for Computer Science Research Computing Facility |
7 | * Rutgers, The State University of New Jersey | 7 | * Rutgers, The State University of New Jersey |
8 | * | 8 | * |
9 | * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406 | 9 | * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406 |
10 | * | 10 | * |
11 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by | 11 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by |
12 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based | 12 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based |
13 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. | 13 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. |
14 | * | 14 | * |
15 | * Migration to usage of "page cache" on May 2006 by | 15 | * Migration to usage of "page cache" on May 2006 by |
16 | * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base. | 16 | * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/time.h> | 19 | #include <linux/time.h> |
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ufs_fs.h> | 21 | #include <linux/ufs_fs.h> |
22 | #include <linux/swap.h> | 22 | #include <linux/swap.h> |
23 | 23 | ||
24 | #include "ufs.h" | ||
24 | #include "swab.h" | 25 | #include "swab.h" |
25 | #include "util.h" | 26 | #include "util.h" |
26 | 27 | ||
27 | /* | 28 | /* |
28 | * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure. | 29 | * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure. |
29 | * | 30 | * |
30 | * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller. | 31 | * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller. |
31 | */ | 32 | */ |
32 | static inline int ufs_match(struct super_block *sb, int len, | 33 | static inline int ufs_match(struct super_block *sb, int len, |
33 | const char * const name, struct ufs_dir_entry * de) | 34 | const char * const name, struct ufs_dir_entry * de) |
34 | { | 35 | { |
35 | if (len != ufs_get_de_namlen(sb, de)) | 36 | if (len != ufs_get_de_namlen(sb, de)) |
36 | return 0; | 37 | return 0; |
37 | if (!de->d_ino) | 38 | if (!de->d_ino) |
38 | return 0; | 39 | return 0; |
39 | return !memcmp(name, de->d_name, len); | 40 | return !memcmp(name, de->d_name, len); |
40 | } | 41 | } |
41 | 42 | ||
42 | static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len) | 43 | static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len) |
43 | { | 44 | { |
44 | struct address_space *mapping = page->mapping; | 45 | struct address_space *mapping = page->mapping; |
45 | struct inode *dir = mapping->host; | 46 | struct inode *dir = mapping->host; |
46 | int err = 0; | 47 | int err = 0; |
47 | 48 | ||
48 | dir->i_version++; | 49 | dir->i_version++; |
49 | block_write_end(NULL, mapping, pos, len, len, page, NULL); | 50 | block_write_end(NULL, mapping, pos, len, len, page, NULL); |
50 | if (pos+len > dir->i_size) { | 51 | if (pos+len > dir->i_size) { |
51 | i_size_write(dir, pos+len); | 52 | i_size_write(dir, pos+len); |
52 | mark_inode_dirty(dir); | 53 | mark_inode_dirty(dir); |
53 | } | 54 | } |
54 | if (IS_DIRSYNC(dir)) | 55 | if (IS_DIRSYNC(dir)) |
55 | err = write_one_page(page, 1); | 56 | err = write_one_page(page, 1); |
56 | else | 57 | else |
57 | unlock_page(page); | 58 | unlock_page(page); |
58 | return err; | 59 | return err; |
59 | } | 60 | } |
60 | 61 | ||
61 | static inline void ufs_put_page(struct page *page) | 62 | static inline void ufs_put_page(struct page *page) |
62 | { | 63 | { |
63 | kunmap(page); | 64 | kunmap(page); |
64 | page_cache_release(page); | 65 | page_cache_release(page); |
65 | } | 66 | } |
66 | 67 | ||
67 | static inline unsigned long ufs_dir_pages(struct inode *inode) | 68 | static inline unsigned long ufs_dir_pages(struct inode *inode) |
68 | { | 69 | { |
69 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; | 70 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; |
70 | } | 71 | } |
71 | 72 | ||
72 | ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry) | 73 | ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry) |
73 | { | 74 | { |
74 | ino_t res = 0; | 75 | ino_t res = 0; |
75 | struct ufs_dir_entry *de; | 76 | struct ufs_dir_entry *de; |
76 | struct page *page; | 77 | struct page *page; |
77 | 78 | ||
78 | de = ufs_find_entry(dir, dentry, &page); | 79 | de = ufs_find_entry(dir, dentry, &page); |
79 | if (de) { | 80 | if (de) { |
80 | res = fs32_to_cpu(dir->i_sb, de->d_ino); | 81 | res = fs32_to_cpu(dir->i_sb, de->d_ino); |
81 | ufs_put_page(page); | 82 | ufs_put_page(page); |
82 | } | 83 | } |
83 | return res; | 84 | return res; |
84 | } | 85 | } |
85 | 86 | ||
86 | 87 | ||
87 | /* Releases the page */ | 88 | /* Releases the page */ |
88 | void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, | 89 | void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, |
89 | struct page *page, struct inode *inode) | 90 | struct page *page, struct inode *inode) |
90 | { | 91 | { |
91 | loff_t pos = page_offset(page) + | 92 | loff_t pos = page_offset(page) + |
92 | (char *) de - (char *) page_address(page); | 93 | (char *) de - (char *) page_address(page); |
93 | unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen); | 94 | unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen); |
94 | int err; | 95 | int err; |
95 | 96 | ||
96 | lock_page(page); | 97 | lock_page(page); |
97 | err = __ufs_write_begin(NULL, page->mapping, pos, len, | 98 | err = __ufs_write_begin(NULL, page->mapping, pos, len, |
98 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | 99 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
99 | BUG_ON(err); | 100 | BUG_ON(err); |
100 | 101 | ||
101 | de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); | 102 | de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); |
102 | ufs_set_de_type(dir->i_sb, de, inode->i_mode); | 103 | ufs_set_de_type(dir->i_sb, de, inode->i_mode); |
103 | 104 | ||
104 | err = ufs_commit_chunk(page, pos, len); | 105 | err = ufs_commit_chunk(page, pos, len); |
105 | ufs_put_page(page); | 106 | ufs_put_page(page); |
106 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 107 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
107 | mark_inode_dirty(dir); | 108 | mark_inode_dirty(dir); |
108 | } | 109 | } |
109 | 110 | ||
110 | 111 | ||
111 | static void ufs_check_page(struct page *page) | 112 | static void ufs_check_page(struct page *page) |
112 | { | 113 | { |
113 | struct inode *dir = page->mapping->host; | 114 | struct inode *dir = page->mapping->host; |
114 | struct super_block *sb = dir->i_sb; | 115 | struct super_block *sb = dir->i_sb; |
115 | char *kaddr = page_address(page); | 116 | char *kaddr = page_address(page); |
116 | unsigned offs, rec_len; | 117 | unsigned offs, rec_len; |
117 | unsigned limit = PAGE_CACHE_SIZE; | 118 | unsigned limit = PAGE_CACHE_SIZE; |
118 | const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1; | 119 | const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1; |
119 | struct ufs_dir_entry *p; | 120 | struct ufs_dir_entry *p; |
120 | char *error; | 121 | char *error; |
121 | 122 | ||
122 | if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { | 123 | if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { |
123 | limit = dir->i_size & ~PAGE_CACHE_MASK; | 124 | limit = dir->i_size & ~PAGE_CACHE_MASK; |
124 | if (limit & chunk_mask) | 125 | if (limit & chunk_mask) |
125 | goto Ebadsize; | 126 | goto Ebadsize; |
126 | if (!limit) | 127 | if (!limit) |
127 | goto out; | 128 | goto out; |
128 | } | 129 | } |
129 | for (offs = 0; offs <= limit - UFS_DIR_REC_LEN(1); offs += rec_len) { | 130 | for (offs = 0; offs <= limit - UFS_DIR_REC_LEN(1); offs += rec_len) { |
130 | p = (struct ufs_dir_entry *)(kaddr + offs); | 131 | p = (struct ufs_dir_entry *)(kaddr + offs); |
131 | rec_len = fs16_to_cpu(sb, p->d_reclen); | 132 | rec_len = fs16_to_cpu(sb, p->d_reclen); |
132 | 133 | ||
133 | if (rec_len < UFS_DIR_REC_LEN(1)) | 134 | if (rec_len < UFS_DIR_REC_LEN(1)) |
134 | goto Eshort; | 135 | goto Eshort; |
135 | if (rec_len & 3) | 136 | if (rec_len & 3) |
136 | goto Ealign; | 137 | goto Ealign; |
137 | if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p))) | 138 | if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p))) |
138 | goto Enamelen; | 139 | goto Enamelen; |
139 | if (((offs + rec_len - 1) ^ offs) & ~chunk_mask) | 140 | if (((offs + rec_len - 1) ^ offs) & ~chunk_mask) |
140 | goto Espan; | 141 | goto Espan; |
141 | if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg * | 142 | if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg * |
142 | UFS_SB(sb)->s_uspi->s_ncg)) | 143 | UFS_SB(sb)->s_uspi->s_ncg)) |
143 | goto Einumber; | 144 | goto Einumber; |
144 | } | 145 | } |
145 | if (offs != limit) | 146 | if (offs != limit) |
146 | goto Eend; | 147 | goto Eend; |
147 | out: | 148 | out: |
148 | SetPageChecked(page); | 149 | SetPageChecked(page); |
149 | return; | 150 | return; |
150 | 151 | ||
151 | /* Too bad, we had an error */ | 152 | /* Too bad, we had an error */ |
152 | 153 | ||
153 | Ebadsize: | 154 | Ebadsize: |
154 | ufs_error(sb, "ufs_check_page", | 155 | ufs_error(sb, "ufs_check_page", |
155 | "size of directory #%lu is not a multiple of chunk size", | 156 | "size of directory #%lu is not a multiple of chunk size", |
156 | dir->i_ino | 157 | dir->i_ino |
157 | ); | 158 | ); |
158 | goto fail; | 159 | goto fail; |
159 | Eshort: | 160 | Eshort: |
160 | error = "rec_len is smaller than minimal"; | 161 | error = "rec_len is smaller than minimal"; |
161 | goto bad_entry; | 162 | goto bad_entry; |
162 | Ealign: | 163 | Ealign: |
163 | error = "unaligned directory entry"; | 164 | error = "unaligned directory entry"; |
164 | goto bad_entry; | 165 | goto bad_entry; |
165 | Enamelen: | 166 | Enamelen: |
166 | error = "rec_len is too small for name_len"; | 167 | error = "rec_len is too small for name_len"; |
167 | goto bad_entry; | 168 | goto bad_entry; |
168 | Espan: | 169 | Espan: |
169 | error = "directory entry across blocks"; | 170 | error = "directory entry across blocks"; |
170 | goto bad_entry; | 171 | goto bad_entry; |
171 | Einumber: | 172 | Einumber: |
172 | error = "inode out of bounds"; | 173 | error = "inode out of bounds"; |
173 | bad_entry: | 174 | bad_entry: |
174 | ufs_error (sb, "ufs_check_page", "bad entry in directory #%lu: %s - " | 175 | ufs_error (sb, "ufs_check_page", "bad entry in directory #%lu: %s - " |
175 | "offset=%lu, rec_len=%d, name_len=%d", | 176 | "offset=%lu, rec_len=%d, name_len=%d", |
176 | dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs, | 177 | dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs, |
177 | rec_len, ufs_get_de_namlen(sb, p)); | 178 | rec_len, ufs_get_de_namlen(sb, p)); |
178 | goto fail; | 179 | goto fail; |
179 | Eend: | 180 | Eend: |
180 | p = (struct ufs_dir_entry *)(kaddr + offs); | 181 | p = (struct ufs_dir_entry *)(kaddr + offs); |
181 | ufs_error (sb, "ext2_check_page", | 182 | ufs_error (sb, "ext2_check_page", |
182 | "entry in directory #%lu spans the page boundary" | 183 | "entry in directory #%lu spans the page boundary" |
183 | "offset=%lu", | 184 | "offset=%lu", |
184 | dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs); | 185 | dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs); |
185 | fail: | 186 | fail: |
186 | SetPageChecked(page); | 187 | SetPageChecked(page); |
187 | SetPageError(page); | 188 | SetPageError(page); |
188 | } | 189 | } |
189 | 190 | ||
190 | static struct page *ufs_get_page(struct inode *dir, unsigned long n) | 191 | static struct page *ufs_get_page(struct inode *dir, unsigned long n) |
191 | { | 192 | { |
192 | struct address_space *mapping = dir->i_mapping; | 193 | struct address_space *mapping = dir->i_mapping; |
193 | struct page *page = read_mapping_page(mapping, n, NULL); | 194 | struct page *page = read_mapping_page(mapping, n, NULL); |
194 | if (!IS_ERR(page)) { | 195 | if (!IS_ERR(page)) { |
195 | kmap(page); | 196 | kmap(page); |
196 | if (!PageChecked(page)) | 197 | if (!PageChecked(page)) |
197 | ufs_check_page(page); | 198 | ufs_check_page(page); |
198 | if (PageError(page)) | 199 | if (PageError(page)) |
199 | goto fail; | 200 | goto fail; |
200 | } | 201 | } |
201 | return page; | 202 | return page; |
202 | 203 | ||
203 | fail: | 204 | fail: |
204 | ufs_put_page(page); | 205 | ufs_put_page(page); |
205 | return ERR_PTR(-EIO); | 206 | return ERR_PTR(-EIO); |
206 | } | 207 | } |
207 | 208 | ||
208 | /* | 209 | /* |
209 | * Return the offset into page `page_nr' of the last valid | 210 | * Return the offset into page `page_nr' of the last valid |
210 | * byte in that page, plus one. | 211 | * byte in that page, plus one. |
211 | */ | 212 | */ |
212 | static unsigned | 213 | static unsigned |
213 | ufs_last_byte(struct inode *inode, unsigned long page_nr) | 214 | ufs_last_byte(struct inode *inode, unsigned long page_nr) |
214 | { | 215 | { |
215 | unsigned last_byte = inode->i_size; | 216 | unsigned last_byte = inode->i_size; |
216 | 217 | ||
217 | last_byte -= page_nr << PAGE_CACHE_SHIFT; | 218 | last_byte -= page_nr << PAGE_CACHE_SHIFT; |
218 | if (last_byte > PAGE_CACHE_SIZE) | 219 | if (last_byte > PAGE_CACHE_SIZE) |
219 | last_byte = PAGE_CACHE_SIZE; | 220 | last_byte = PAGE_CACHE_SIZE; |
220 | return last_byte; | 221 | return last_byte; |
221 | } | 222 | } |
222 | 223 | ||
223 | static inline struct ufs_dir_entry * | 224 | static inline struct ufs_dir_entry * |
224 | ufs_next_entry(struct super_block *sb, struct ufs_dir_entry *p) | 225 | ufs_next_entry(struct super_block *sb, struct ufs_dir_entry *p) |
225 | { | 226 | { |
226 | return (struct ufs_dir_entry *)((char *)p + | 227 | return (struct ufs_dir_entry *)((char *)p + |
227 | fs16_to_cpu(sb, p->d_reclen)); | 228 | fs16_to_cpu(sb, p->d_reclen)); |
228 | } | 229 | } |
229 | 230 | ||
230 | struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p) | 231 | struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p) |
231 | { | 232 | { |
232 | struct page *page = ufs_get_page(dir, 0); | 233 | struct page *page = ufs_get_page(dir, 0); |
233 | struct ufs_dir_entry *de = NULL; | 234 | struct ufs_dir_entry *de = NULL; |
234 | 235 | ||
235 | if (!IS_ERR(page)) { | 236 | if (!IS_ERR(page)) { |
236 | de = ufs_next_entry(dir->i_sb, | 237 | de = ufs_next_entry(dir->i_sb, |
237 | (struct ufs_dir_entry *)page_address(page)); | 238 | (struct ufs_dir_entry *)page_address(page)); |
238 | *p = page; | 239 | *p = page; |
239 | } | 240 | } |
240 | return de; | 241 | return de; |
241 | } | 242 | } |
242 | 243 | ||
243 | /* | 244 | /* |
244 | * ufs_find_entry() | 245 | * ufs_find_entry() |
245 | * | 246 | * |
246 | * finds an entry in the specified directory with the wanted name. It | 247 | * finds an entry in the specified directory with the wanted name. It |
247 | * returns the page in which the entry was found, and the entry itself | 248 | * returns the page in which the entry was found, and the entry itself |
248 | * (as a parameter - res_dir). Page is returned mapped and unlocked. | 249 | * (as a parameter - res_dir). Page is returned mapped and unlocked. |
249 | * Entry is guaranteed to be valid. | 250 | * Entry is guaranteed to be valid. |
250 | */ | 251 | */ |
251 | struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry, | 252 | struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry, |
252 | struct page **res_page) | 253 | struct page **res_page) |
253 | { | 254 | { |
254 | struct super_block *sb = dir->i_sb; | 255 | struct super_block *sb = dir->i_sb; |
255 | const char *name = dentry->d_name.name; | 256 | const char *name = dentry->d_name.name; |
256 | int namelen = dentry->d_name.len; | 257 | int namelen = dentry->d_name.len; |
257 | unsigned reclen = UFS_DIR_REC_LEN(namelen); | 258 | unsigned reclen = UFS_DIR_REC_LEN(namelen); |
258 | unsigned long start, n; | 259 | unsigned long start, n; |
259 | unsigned long npages = ufs_dir_pages(dir); | 260 | unsigned long npages = ufs_dir_pages(dir); |
260 | struct page *page = NULL; | 261 | struct page *page = NULL; |
261 | struct ufs_inode_info *ui = UFS_I(dir); | 262 | struct ufs_inode_info *ui = UFS_I(dir); |
262 | struct ufs_dir_entry *de; | 263 | struct ufs_dir_entry *de; |
263 | 264 | ||
264 | UFSD("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen); | 265 | UFSD("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen); |
265 | 266 | ||
266 | if (npages == 0 || namelen > UFS_MAXNAMLEN) | 267 | if (npages == 0 || namelen > UFS_MAXNAMLEN) |
267 | goto out; | 268 | goto out; |
268 | 269 | ||
269 | /* OFFSET_CACHE */ | 270 | /* OFFSET_CACHE */ |
270 | *res_page = NULL; | 271 | *res_page = NULL; |
271 | 272 | ||
272 | start = ui->i_dir_start_lookup; | 273 | start = ui->i_dir_start_lookup; |
273 | 274 | ||
274 | if (start >= npages) | 275 | if (start >= npages) |
275 | start = 0; | 276 | start = 0; |
276 | n = start; | 277 | n = start; |
277 | do { | 278 | do { |
278 | char *kaddr; | 279 | char *kaddr; |
279 | page = ufs_get_page(dir, n); | 280 | page = ufs_get_page(dir, n); |
280 | if (!IS_ERR(page)) { | 281 | if (!IS_ERR(page)) { |
281 | kaddr = page_address(page); | 282 | kaddr = page_address(page); |
282 | de = (struct ufs_dir_entry *) kaddr; | 283 | de = (struct ufs_dir_entry *) kaddr; |
283 | kaddr += ufs_last_byte(dir, n) - reclen; | 284 | kaddr += ufs_last_byte(dir, n) - reclen; |
284 | while ((char *) de <= kaddr) { | 285 | while ((char *) de <= kaddr) { |
285 | if (de->d_reclen == 0) { | 286 | if (de->d_reclen == 0) { |
286 | ufs_error(dir->i_sb, __FUNCTION__, | 287 | ufs_error(dir->i_sb, __FUNCTION__, |
287 | "zero-length directory entry"); | 288 | "zero-length directory entry"); |
288 | ufs_put_page(page); | 289 | ufs_put_page(page); |
289 | goto out; | 290 | goto out; |
290 | } | 291 | } |
291 | if (ufs_match(sb, namelen, name, de)) | 292 | if (ufs_match(sb, namelen, name, de)) |
292 | goto found; | 293 | goto found; |
293 | de = ufs_next_entry(sb, de); | 294 | de = ufs_next_entry(sb, de); |
294 | } | 295 | } |
295 | ufs_put_page(page); | 296 | ufs_put_page(page); |
296 | } | 297 | } |
297 | if (++n >= npages) | 298 | if (++n >= npages) |
298 | n = 0; | 299 | n = 0; |
299 | } while (n != start); | 300 | } while (n != start); |
300 | out: | 301 | out: |
301 | return NULL; | 302 | return NULL; |
302 | 303 | ||
303 | found: | 304 | found: |
304 | *res_page = page; | 305 | *res_page = page; |
305 | ui->i_dir_start_lookup = n; | 306 | ui->i_dir_start_lookup = n; |
306 | return de; | 307 | return de; |
307 | } | 308 | } |
308 | 309 | ||
309 | /* | 310 | /* |
310 | * Parent is locked. | 311 | * Parent is locked. |
311 | */ | 312 | */ |
312 | int ufs_add_link(struct dentry *dentry, struct inode *inode) | 313 | int ufs_add_link(struct dentry *dentry, struct inode *inode) |
313 | { | 314 | { |
314 | struct inode *dir = dentry->d_parent->d_inode; | 315 | struct inode *dir = dentry->d_parent->d_inode; |
315 | const char *name = dentry->d_name.name; | 316 | const char *name = dentry->d_name.name; |
316 | int namelen = dentry->d_name.len; | 317 | int namelen = dentry->d_name.len; |
317 | struct super_block *sb = dir->i_sb; | 318 | struct super_block *sb = dir->i_sb; |
318 | unsigned reclen = UFS_DIR_REC_LEN(namelen); | 319 | unsigned reclen = UFS_DIR_REC_LEN(namelen); |
319 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; | 320 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; |
320 | unsigned short rec_len, name_len; | 321 | unsigned short rec_len, name_len; |
321 | struct page *page = NULL; | 322 | struct page *page = NULL; |
322 | struct ufs_dir_entry *de; | 323 | struct ufs_dir_entry *de; |
323 | unsigned long npages = ufs_dir_pages(dir); | 324 | unsigned long npages = ufs_dir_pages(dir); |
324 | unsigned long n; | 325 | unsigned long n; |
325 | char *kaddr; | 326 | char *kaddr; |
326 | loff_t pos; | 327 | loff_t pos; |
327 | int err; | 328 | int err; |
328 | 329 | ||
329 | UFSD("ENTER, name %s, namelen %u\n", name, namelen); | 330 | UFSD("ENTER, name %s, namelen %u\n", name, namelen); |
330 | 331 | ||
331 | /* | 332 | /* |
332 | * We take care of directory expansion in the same loop. | 333 | * We take care of directory expansion in the same loop. |
333 | * This code plays outside i_size, so it locks the page | 334 | * This code plays outside i_size, so it locks the page |
334 | * to protect that region. | 335 | * to protect that region. |
335 | */ | 336 | */ |
336 | for (n = 0; n <= npages; n++) { | 337 | for (n = 0; n <= npages; n++) { |
337 | char *dir_end; | 338 | char *dir_end; |
338 | 339 | ||
339 | page = ufs_get_page(dir, n); | 340 | page = ufs_get_page(dir, n); |
340 | err = PTR_ERR(page); | 341 | err = PTR_ERR(page); |
341 | if (IS_ERR(page)) | 342 | if (IS_ERR(page)) |
342 | goto out; | 343 | goto out; |
343 | lock_page(page); | 344 | lock_page(page); |
344 | kaddr = page_address(page); | 345 | kaddr = page_address(page); |
345 | dir_end = kaddr + ufs_last_byte(dir, n); | 346 | dir_end = kaddr + ufs_last_byte(dir, n); |
346 | de = (struct ufs_dir_entry *)kaddr; | 347 | de = (struct ufs_dir_entry *)kaddr; |
347 | kaddr += PAGE_CACHE_SIZE - reclen; | 348 | kaddr += PAGE_CACHE_SIZE - reclen; |
348 | while ((char *)de <= kaddr) { | 349 | while ((char *)de <= kaddr) { |
349 | if ((char *)de == dir_end) { | 350 | if ((char *)de == dir_end) { |
350 | /* We hit i_size */ | 351 | /* We hit i_size */ |
351 | name_len = 0; | 352 | name_len = 0; |
352 | rec_len = chunk_size; | 353 | rec_len = chunk_size; |
353 | de->d_reclen = cpu_to_fs16(sb, chunk_size); | 354 | de->d_reclen = cpu_to_fs16(sb, chunk_size); |
354 | de->d_ino = 0; | 355 | de->d_ino = 0; |
355 | goto got_it; | 356 | goto got_it; |
356 | } | 357 | } |
357 | if (de->d_reclen == 0) { | 358 | if (de->d_reclen == 0) { |
358 | ufs_error(dir->i_sb, __FUNCTION__, | 359 | ufs_error(dir->i_sb, __FUNCTION__, |
359 | "zero-length directory entry"); | 360 | "zero-length directory entry"); |
360 | err = -EIO; | 361 | err = -EIO; |
361 | goto out_unlock; | 362 | goto out_unlock; |
362 | } | 363 | } |
363 | err = -EEXIST; | 364 | err = -EEXIST; |
364 | if (ufs_match(sb, namelen, name, de)) | 365 | if (ufs_match(sb, namelen, name, de)) |
365 | goto out_unlock; | 366 | goto out_unlock; |
366 | name_len = UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)); | 367 | name_len = UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)); |
367 | rec_len = fs16_to_cpu(sb, de->d_reclen); | 368 | rec_len = fs16_to_cpu(sb, de->d_reclen); |
368 | if (!de->d_ino && rec_len >= reclen) | 369 | if (!de->d_ino && rec_len >= reclen) |
369 | goto got_it; | 370 | goto got_it; |
370 | if (rec_len >= name_len + reclen) | 371 | if (rec_len >= name_len + reclen) |
371 | goto got_it; | 372 | goto got_it; |
372 | de = (struct ufs_dir_entry *) ((char *) de + rec_len); | 373 | de = (struct ufs_dir_entry *) ((char *) de + rec_len); |
373 | } | 374 | } |
374 | unlock_page(page); | 375 | unlock_page(page); |
375 | ufs_put_page(page); | 376 | ufs_put_page(page); |
376 | } | 377 | } |
377 | BUG(); | 378 | BUG(); |
378 | return -EINVAL; | 379 | return -EINVAL; |
379 | 380 | ||
380 | got_it: | 381 | got_it: |
381 | pos = page_offset(page) + | 382 | pos = page_offset(page) + |
382 | (char*)de - (char*)page_address(page); | 383 | (char*)de - (char*)page_address(page); |
383 | err = __ufs_write_begin(NULL, page->mapping, pos, rec_len, | 384 | err = __ufs_write_begin(NULL, page->mapping, pos, rec_len, |
384 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | 385 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
385 | if (err) | 386 | if (err) |
386 | goto out_unlock; | 387 | goto out_unlock; |
387 | if (de->d_ino) { | 388 | if (de->d_ino) { |
388 | struct ufs_dir_entry *de1 = | 389 | struct ufs_dir_entry *de1 = |
389 | (struct ufs_dir_entry *) ((char *) de + name_len); | 390 | (struct ufs_dir_entry *) ((char *) de + name_len); |
390 | de1->d_reclen = cpu_to_fs16(sb, rec_len - name_len); | 391 | de1->d_reclen = cpu_to_fs16(sb, rec_len - name_len); |
391 | de->d_reclen = cpu_to_fs16(sb, name_len); | 392 | de->d_reclen = cpu_to_fs16(sb, name_len); |
392 | 393 | ||
393 | de = de1; | 394 | de = de1; |
394 | } | 395 | } |
395 | 396 | ||
396 | ufs_set_de_namlen(sb, de, namelen); | 397 | ufs_set_de_namlen(sb, de, namelen); |
397 | memcpy(de->d_name, name, namelen + 1); | 398 | memcpy(de->d_name, name, namelen + 1); |
398 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); | 399 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); |
399 | ufs_set_de_type(sb, de, inode->i_mode); | 400 | ufs_set_de_type(sb, de, inode->i_mode); |
400 | 401 | ||
401 | err = ufs_commit_chunk(page, pos, rec_len); | 402 | err = ufs_commit_chunk(page, pos, rec_len); |
402 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 403 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
403 | 404 | ||
404 | mark_inode_dirty(dir); | 405 | mark_inode_dirty(dir); |
405 | /* OFFSET_CACHE */ | 406 | /* OFFSET_CACHE */ |
406 | out_put: | 407 | out_put: |
407 | ufs_put_page(page); | 408 | ufs_put_page(page); |
408 | out: | 409 | out: |
409 | return err; | 410 | return err; |
410 | out_unlock: | 411 | out_unlock: |
411 | unlock_page(page); | 412 | unlock_page(page); |
412 | goto out_put; | 413 | goto out_put; |
413 | } | 414 | } |
414 | 415 | ||
415 | static inline unsigned | 416 | static inline unsigned |
416 | ufs_validate_entry(struct super_block *sb, char *base, | 417 | ufs_validate_entry(struct super_block *sb, char *base, |
417 | unsigned offset, unsigned mask) | 418 | unsigned offset, unsigned mask) |
418 | { | 419 | { |
419 | struct ufs_dir_entry *de = (struct ufs_dir_entry*)(base + offset); | 420 | struct ufs_dir_entry *de = (struct ufs_dir_entry*)(base + offset); |
420 | struct ufs_dir_entry *p = (struct ufs_dir_entry*)(base + (offset&mask)); | 421 | struct ufs_dir_entry *p = (struct ufs_dir_entry*)(base + (offset&mask)); |
421 | while ((char*)p < (char*)de) { | 422 | while ((char*)p < (char*)de) { |
422 | if (p->d_reclen == 0) | 423 | if (p->d_reclen == 0) |
423 | break; | 424 | break; |
424 | p = ufs_next_entry(sb, p); | 425 | p = ufs_next_entry(sb, p); |
425 | } | 426 | } |
426 | return (char *)p - base; | 427 | return (char *)p - base; |
427 | } | 428 | } |
428 | 429 | ||
429 | 430 | ||
430 | /* | 431 | /* |
431 | * This is blatantly stolen from ext2fs | 432 | * This is blatantly stolen from ext2fs |
432 | */ | 433 | */ |
433 | static int | 434 | static int |
434 | ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 435 | ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) |
435 | { | 436 | { |
436 | loff_t pos = filp->f_pos; | 437 | loff_t pos = filp->f_pos; |
437 | struct inode *inode = filp->f_path.dentry->d_inode; | 438 | struct inode *inode = filp->f_path.dentry->d_inode; |
438 | struct super_block *sb = inode->i_sb; | 439 | struct super_block *sb = inode->i_sb; |
439 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | 440 | unsigned int offset = pos & ~PAGE_CACHE_MASK; |
440 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 441 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
441 | unsigned long npages = ufs_dir_pages(inode); | 442 | unsigned long npages = ufs_dir_pages(inode); |
442 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); | 443 | unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
443 | int need_revalidate = filp->f_version != inode->i_version; | 444 | int need_revalidate = filp->f_version != inode->i_version; |
444 | unsigned flags = UFS_SB(sb)->s_flags; | 445 | unsigned flags = UFS_SB(sb)->s_flags; |
445 | 446 | ||
446 | UFSD("BEGIN\n"); | 447 | UFSD("BEGIN\n"); |
447 | 448 | ||
448 | if (pos > inode->i_size - UFS_DIR_REC_LEN(1)) | 449 | if (pos > inode->i_size - UFS_DIR_REC_LEN(1)) |
449 | return 0; | 450 | return 0; |
450 | 451 | ||
451 | for ( ; n < npages; n++, offset = 0) { | 452 | for ( ; n < npages; n++, offset = 0) { |
452 | char *kaddr, *limit; | 453 | char *kaddr, *limit; |
453 | struct ufs_dir_entry *de; | 454 | struct ufs_dir_entry *de; |
454 | 455 | ||
455 | struct page *page = ufs_get_page(inode, n); | 456 | struct page *page = ufs_get_page(inode, n); |
456 | 457 | ||
457 | if (IS_ERR(page)) { | 458 | if (IS_ERR(page)) { |
458 | ufs_error(sb, __FUNCTION__, | 459 | ufs_error(sb, __FUNCTION__, |
459 | "bad page in #%lu", | 460 | "bad page in #%lu", |
460 | inode->i_ino); | 461 | inode->i_ino); |
461 | filp->f_pos += PAGE_CACHE_SIZE - offset; | 462 | filp->f_pos += PAGE_CACHE_SIZE - offset; |
462 | return -EIO; | 463 | return -EIO; |
463 | } | 464 | } |
464 | kaddr = page_address(page); | 465 | kaddr = page_address(page); |
465 | if (unlikely(need_revalidate)) { | 466 | if (unlikely(need_revalidate)) { |
466 | if (offset) { | 467 | if (offset) { |
467 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); | 468 | offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask); |
468 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | 469 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; |
469 | } | 470 | } |
470 | filp->f_version = inode->i_version; | 471 | filp->f_version = inode->i_version; |
471 | need_revalidate = 0; | 472 | need_revalidate = 0; |
472 | } | 473 | } |
473 | de = (struct ufs_dir_entry *)(kaddr+offset); | 474 | de = (struct ufs_dir_entry *)(kaddr+offset); |
474 | limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1); | 475 | limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1); |
475 | for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) { | 476 | for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) { |
476 | if (de->d_reclen == 0) { | 477 | if (de->d_reclen == 0) { |
477 | ufs_error(sb, __FUNCTION__, | 478 | ufs_error(sb, __FUNCTION__, |
478 | "zero-length directory entry"); | 479 | "zero-length directory entry"); |
479 | ufs_put_page(page); | 480 | ufs_put_page(page); |
480 | return -EIO; | 481 | return -EIO; |
481 | } | 482 | } |
482 | if (de->d_ino) { | 483 | if (de->d_ino) { |
483 | int over; | 484 | int over; |
484 | unsigned char d_type = DT_UNKNOWN; | 485 | unsigned char d_type = DT_UNKNOWN; |
485 | 486 | ||
486 | offset = (char *)de - kaddr; | 487 | offset = (char *)de - kaddr; |
487 | 488 | ||
488 | UFSD("filldir(%s,%u)\n", de->d_name, | 489 | UFSD("filldir(%s,%u)\n", de->d_name, |
489 | fs32_to_cpu(sb, de->d_ino)); | 490 | fs32_to_cpu(sb, de->d_ino)); |
490 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); | 491 | UFSD("namlen %u\n", ufs_get_de_namlen(sb, de)); |
491 | 492 | ||
492 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) | 493 | if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) |
493 | d_type = de->d_u.d_44.d_type; | 494 | d_type = de->d_u.d_44.d_type; |
494 | 495 | ||
495 | over = filldir(dirent, de->d_name, | 496 | over = filldir(dirent, de->d_name, |
496 | ufs_get_de_namlen(sb, de), | 497 | ufs_get_de_namlen(sb, de), |
497 | (n<<PAGE_CACHE_SHIFT) | offset, | 498 | (n<<PAGE_CACHE_SHIFT) | offset, |
498 | fs32_to_cpu(sb, de->d_ino), d_type); | 499 | fs32_to_cpu(sb, de->d_ino), d_type); |
499 | if (over) { | 500 | if (over) { |
500 | ufs_put_page(page); | 501 | ufs_put_page(page); |
501 | return 0; | 502 | return 0; |
502 | } | 503 | } |
503 | } | 504 | } |
504 | filp->f_pos += fs16_to_cpu(sb, de->d_reclen); | 505 | filp->f_pos += fs16_to_cpu(sb, de->d_reclen); |
505 | } | 506 | } |
506 | ufs_put_page(page); | 507 | ufs_put_page(page); |
507 | } | 508 | } |
508 | return 0; | 509 | return 0; |
509 | } | 510 | } |
510 | 511 | ||
511 | 512 | ||
512 | /* | 513 | /* |
513 | * ufs_delete_entry deletes a directory entry by merging it with the | 514 | * ufs_delete_entry deletes a directory entry by merging it with the |
514 | * previous entry. | 515 | * previous entry. |
515 | */ | 516 | */ |
516 | int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, | 517 | int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, |
517 | struct page * page) | 518 | struct page * page) |
518 | { | 519 | { |
519 | struct super_block *sb = inode->i_sb; | 520 | struct super_block *sb = inode->i_sb; |
520 | struct address_space *mapping = page->mapping; | 521 | struct address_space *mapping = page->mapping; |
521 | char *kaddr = page_address(page); | 522 | char *kaddr = page_address(page); |
522 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); | 523 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
523 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); | 524 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); |
524 | loff_t pos; | 525 | loff_t pos; |
525 | struct ufs_dir_entry *pde = NULL; | 526 | struct ufs_dir_entry *pde = NULL; |
526 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); | 527 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); |
527 | int err; | 528 | int err; |
528 | 529 | ||
529 | UFSD("ENTER\n"); | 530 | UFSD("ENTER\n"); |
530 | 531 | ||
531 | UFSD("ino %u, reclen %u, namlen %u, name %s\n", | 532 | UFSD("ino %u, reclen %u, namlen %u, name %s\n", |
532 | fs32_to_cpu(sb, de->d_ino), | 533 | fs32_to_cpu(sb, de->d_ino), |
533 | fs16_to_cpu(sb, de->d_reclen), | 534 | fs16_to_cpu(sb, de->d_reclen), |
534 | ufs_get_de_namlen(sb, de), de->d_name); | 535 | ufs_get_de_namlen(sb, de), de->d_name); |
535 | 536 | ||
536 | while ((char*)de < (char*)dir) { | 537 | while ((char*)de < (char*)dir) { |
537 | if (de->d_reclen == 0) { | 538 | if (de->d_reclen == 0) { |
538 | ufs_error(inode->i_sb, __FUNCTION__, | 539 | ufs_error(inode->i_sb, __FUNCTION__, |
539 | "zero-length directory entry"); | 540 | "zero-length directory entry"); |
540 | err = -EIO; | 541 | err = -EIO; |
541 | goto out; | 542 | goto out; |
542 | } | 543 | } |
543 | pde = de; | 544 | pde = de; |
544 | de = ufs_next_entry(sb, de); | 545 | de = ufs_next_entry(sb, de); |
545 | } | 546 | } |
546 | if (pde) | 547 | if (pde) |
547 | from = (char*)pde - (char*)page_address(page); | 548 | from = (char*)pde - (char*)page_address(page); |
548 | 549 | ||
549 | pos = page_offset(page) + from; | 550 | pos = page_offset(page) + from; |
550 | lock_page(page); | 551 | lock_page(page); |
551 | err = __ufs_write_begin(NULL, mapping, pos, to - from, | 552 | err = __ufs_write_begin(NULL, mapping, pos, to - from, |
552 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | 553 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
553 | BUG_ON(err); | 554 | BUG_ON(err); |
554 | if (pde) | 555 | if (pde) |
555 | pde->d_reclen = cpu_to_fs16(sb, to - from); | 556 | pde->d_reclen = cpu_to_fs16(sb, to - from); |
556 | dir->d_ino = 0; | 557 | dir->d_ino = 0; |
557 | err = ufs_commit_chunk(page, pos, to - from); | 558 | err = ufs_commit_chunk(page, pos, to - from); |
558 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 559 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
559 | mark_inode_dirty(inode); | 560 | mark_inode_dirty(inode); |
560 | out: | 561 | out: |
561 | ufs_put_page(page); | 562 | ufs_put_page(page); |
562 | UFSD("EXIT\n"); | 563 | UFSD("EXIT\n"); |
563 | return err; | 564 | return err; |
564 | } | 565 | } |
565 | 566 | ||
566 | int ufs_make_empty(struct inode * inode, struct inode *dir) | 567 | int ufs_make_empty(struct inode * inode, struct inode *dir) |
567 | { | 568 | { |
568 | struct super_block * sb = dir->i_sb; | 569 | struct super_block * sb = dir->i_sb; |
569 | struct address_space *mapping = inode->i_mapping; | 570 | struct address_space *mapping = inode->i_mapping; |
570 | struct page *page = grab_cache_page(mapping, 0); | 571 | struct page *page = grab_cache_page(mapping, 0); |
571 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; | 572 | const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize; |
572 | struct ufs_dir_entry * de; | 573 | struct ufs_dir_entry * de; |
573 | char *base; | 574 | char *base; |
574 | int err; | 575 | int err; |
575 | 576 | ||
576 | if (!page) | 577 | if (!page) |
577 | return -ENOMEM; | 578 | return -ENOMEM; |
578 | 579 | ||
579 | err = __ufs_write_begin(NULL, mapping, 0, chunk_size, | 580 | err = __ufs_write_begin(NULL, mapping, 0, chunk_size, |
580 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | 581 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
581 | if (err) { | 582 | if (err) { |
582 | unlock_page(page); | 583 | unlock_page(page); |
583 | goto fail; | 584 | goto fail; |
584 | } | 585 | } |
585 | 586 | ||
586 | kmap(page); | 587 | kmap(page); |
587 | base = (char*)page_address(page); | 588 | base = (char*)page_address(page); |
588 | memset(base, 0, PAGE_CACHE_SIZE); | 589 | memset(base, 0, PAGE_CACHE_SIZE); |
589 | 590 | ||
590 | de = (struct ufs_dir_entry *) base; | 591 | de = (struct ufs_dir_entry *) base; |
591 | 592 | ||
592 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); | 593 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); |
593 | ufs_set_de_type(sb, de, inode->i_mode); | 594 | ufs_set_de_type(sb, de, inode->i_mode); |
594 | ufs_set_de_namlen(sb, de, 1); | 595 | ufs_set_de_namlen(sb, de, 1); |
595 | de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1)); | 596 | de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1)); |
596 | strcpy (de->d_name, "."); | 597 | strcpy (de->d_name, "."); |
597 | de = (struct ufs_dir_entry *) | 598 | de = (struct ufs_dir_entry *) |
598 | ((char *)de + fs16_to_cpu(sb, de->d_reclen)); | 599 | ((char *)de + fs16_to_cpu(sb, de->d_reclen)); |
599 | de->d_ino = cpu_to_fs32(sb, dir->i_ino); | 600 | de->d_ino = cpu_to_fs32(sb, dir->i_ino); |
600 | ufs_set_de_type(sb, de, dir->i_mode); | 601 | ufs_set_de_type(sb, de, dir->i_mode); |
601 | de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); | 602 | de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); |
602 | ufs_set_de_namlen(sb, de, 2); | 603 | ufs_set_de_namlen(sb, de, 2); |
603 | strcpy (de->d_name, ".."); | 604 | strcpy (de->d_name, ".."); |
604 | kunmap(page); | 605 | kunmap(page); |
605 | 606 | ||
606 | err = ufs_commit_chunk(page, 0, chunk_size); | 607 | err = ufs_commit_chunk(page, 0, chunk_size); |
607 | fail: | 608 | fail: |
608 | page_cache_release(page); | 609 | page_cache_release(page); |
609 | return err; | 610 | return err; |
610 | } | 611 | } |
611 | 612 | ||
612 | /* | 613 | /* |
613 | * routine to check that the specified directory is empty (for rmdir) | 614 | * routine to check that the specified directory is empty (for rmdir) |
614 | */ | 615 | */ |
615 | int ufs_empty_dir(struct inode * inode) | 616 | int ufs_empty_dir(struct inode * inode) |
616 | { | 617 | { |
617 | struct super_block *sb = inode->i_sb; | 618 | struct super_block *sb = inode->i_sb; |
618 | struct page *page = NULL; | 619 | struct page *page = NULL; |
619 | unsigned long i, npages = ufs_dir_pages(inode); | 620 | unsigned long i, npages = ufs_dir_pages(inode); |
620 | 621 | ||
621 | for (i = 0; i < npages; i++) { | 622 | for (i = 0; i < npages; i++) { |
622 | char *kaddr; | 623 | char *kaddr; |
623 | struct ufs_dir_entry *de; | 624 | struct ufs_dir_entry *de; |
624 | page = ufs_get_page(inode, i); | 625 | page = ufs_get_page(inode, i); |
625 | 626 | ||
626 | if (IS_ERR(page)) | 627 | if (IS_ERR(page)) |
627 | continue; | 628 | continue; |
628 | 629 | ||
629 | kaddr = page_address(page); | 630 | kaddr = page_address(page); |
630 | de = (struct ufs_dir_entry *)kaddr; | 631 | de = (struct ufs_dir_entry *)kaddr; |
631 | kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1); | 632 | kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1); |
632 | 633 | ||
633 | while ((char *)de <= kaddr) { | 634 | while ((char *)de <= kaddr) { |
634 | if (de->d_reclen == 0) { | 635 | if (de->d_reclen == 0) { |
635 | ufs_error(inode->i_sb, __FUNCTION__, | 636 | ufs_error(inode->i_sb, __FUNCTION__, |
636 | "zero-length directory entry: " | 637 | "zero-length directory entry: " |
637 | "kaddr=%p, de=%p\n", kaddr, de); | 638 | "kaddr=%p, de=%p\n", kaddr, de); |
638 | goto not_empty; | 639 | goto not_empty; |
639 | } | 640 | } |
640 | if (de->d_ino) { | 641 | if (de->d_ino) { |
641 | u16 namelen=ufs_get_de_namlen(sb, de); | 642 | u16 namelen=ufs_get_de_namlen(sb, de); |
642 | /* check for . and .. */ | 643 | /* check for . and .. */ |
643 | if (de->d_name[0] != '.') | 644 | if (de->d_name[0] != '.') |
644 | goto not_empty; | 645 | goto not_empty; |
645 | if (namelen > 2) | 646 | if (namelen > 2) |
646 | goto not_empty; | 647 | goto not_empty; |
647 | if (namelen < 2) { | 648 | if (namelen < 2) { |
648 | if (inode->i_ino != | 649 | if (inode->i_ino != |
649 | fs32_to_cpu(sb, de->d_ino)) | 650 | fs32_to_cpu(sb, de->d_ino)) |
650 | goto not_empty; | 651 | goto not_empty; |
651 | } else if (de->d_name[1] != '.') | 652 | } else if (de->d_name[1] != '.') |
652 | goto not_empty; | 653 | goto not_empty; |
653 | } | 654 | } |
654 | de = ufs_next_entry(sb, de); | 655 | de = ufs_next_entry(sb, de); |
655 | } | 656 | } |
656 | ufs_put_page(page); | 657 | ufs_put_page(page); |
657 | } | 658 | } |
658 | return 1; | 659 | return 1; |
659 | 660 | ||
660 | not_empty: | 661 | not_empty: |
661 | ufs_put_page(page); | 662 | ufs_put_page(page); |
662 | return 0; | 663 | return 0; |
663 | } | 664 | } |
664 | 665 | ||
665 | const struct file_operations ufs_dir_operations = { | 666 | const struct file_operations ufs_dir_operations = { |
666 | .read = generic_read_dir, | 667 | .read = generic_read_dir, |
667 | .readdir = ufs_readdir, | 668 | .readdir = ufs_readdir, |
668 | .fsync = file_fsync, | 669 | .fsync = file_fsync, |
669 | }; | 670 | }; |
670 | 671 |
fs/ufs/file.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/file.c | 2 | * linux/fs/ufs/file.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * from | 8 | * from |
9 | * | 9 | * |
10 | * linux/fs/ext2/file.c | 10 | * linux/fs/ext2/file.c |
11 | * | 11 | * |
12 | * Copyright (C) 1992, 1993, 1994, 1995 | 12 | * Copyright (C) 1992, 1993, 1994, 1995 |
13 | * Remy Card (card@masi.ibp.fr) | 13 | * Remy Card (card@masi.ibp.fr) |
14 | * Laboratoire MASI - Institut Blaise Pascal | 14 | * Laboratoire MASI - Institut Blaise Pascal |
15 | * Universite Pierre et Marie Curie (Paris VI) | 15 | * Universite Pierre et Marie Curie (Paris VI) |
16 | * | 16 | * |
17 | * from | 17 | * from |
18 | * | 18 | * |
19 | * linux/fs/minix/file.c | 19 | * linux/fs/minix/file.c |
20 | * | 20 | * |
21 | * Copyright (C) 1991, 1992 Linus Torvalds | 21 | * Copyright (C) 1991, 1992 Linus Torvalds |
22 | * | 22 | * |
23 | * ext2 fs regular file handling primitives | 23 | * ext2 fs regular file handling primitives |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/ufs_fs.h> | 27 | #include <linux/ufs_fs.h> |
28 | #include <linux/buffer_head.h> /* for sync_mapping_buffers() */ | 28 | #include <linux/buffer_head.h> /* for sync_mapping_buffers() */ |
29 | 29 | ||
30 | #include "ufs.h" | ||
31 | |||
32 | |||
30 | static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync) | 33 | static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync) |
31 | { | 34 | { |
32 | struct inode *inode = dentry->d_inode; | 35 | struct inode *inode = dentry->d_inode; |
33 | int err; | 36 | int err; |
34 | int ret; | 37 | int ret; |
35 | 38 | ||
36 | ret = sync_mapping_buffers(inode->i_mapping); | 39 | ret = sync_mapping_buffers(inode->i_mapping); |
37 | if (!(inode->i_state & I_DIRTY)) | 40 | if (!(inode->i_state & I_DIRTY)) |
38 | return ret; | 41 | return ret; |
39 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 42 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
40 | return ret; | 43 | return ret; |
41 | 44 | ||
42 | err = ufs_sync_inode(inode); | 45 | err = ufs_sync_inode(inode); |
43 | if (ret == 0) | 46 | if (ret == 0) |
44 | ret = err; | 47 | ret = err; |
45 | return ret; | 48 | return ret; |
46 | } | 49 | } |
47 | 50 | ||
48 | 51 | ||
49 | /* | 52 | /* |
50 | * We have mostly NULL's here: the current defaults are ok for | 53 | * We have mostly NULL's here: the current defaults are ok for |
51 | * the ufs filesystem. | 54 | * the ufs filesystem. |
52 | */ | 55 | */ |
53 | 56 | ||
54 | const struct file_operations ufs_file_operations = { | 57 | const struct file_operations ufs_file_operations = { |
55 | .llseek = generic_file_llseek, | 58 | .llseek = generic_file_llseek, |
56 | .read = do_sync_read, | 59 | .read = do_sync_read, |
57 | .aio_read = generic_file_aio_read, | 60 | .aio_read = generic_file_aio_read, |
58 | .write = do_sync_write, | 61 | .write = do_sync_write, |
59 | .aio_write = generic_file_aio_write, | 62 | .aio_write = generic_file_aio_write, |
60 | .mmap = generic_file_mmap, | 63 | .mmap = generic_file_mmap, |
61 | .open = generic_file_open, | 64 | .open = generic_file_open, |
62 | .fsync = ufs_sync_file, | 65 | .fsync = ufs_sync_file, |
63 | .splice_read = generic_file_splice_read, | 66 | .splice_read = generic_file_splice_read, |
64 | }; | 67 | }; |
65 | 68 |
fs/ufs/ialloc.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/ialloc.c | 2 | * linux/fs/ufs/ialloc.c |
3 | * | 3 | * |
4 | * Copyright (c) 1998 | 4 | * Copyright (c) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * from | 8 | * from |
9 | * | 9 | * |
10 | * linux/fs/ext2/ialloc.c | 10 | * linux/fs/ext2/ialloc.c |
11 | * | 11 | * |
12 | * Copyright (C) 1992, 1993, 1994, 1995 | 12 | * Copyright (C) 1992, 1993, 1994, 1995 |
13 | * Remy Card (card@masi.ibp.fr) | 13 | * Remy Card (card@masi.ibp.fr) |
14 | * Laboratoire MASI - Institut Blaise Pascal | 14 | * Laboratoire MASI - Institut Blaise Pascal |
15 | * Universite Pierre et Marie Curie (Paris VI) | 15 | * Universite Pierre et Marie Curie (Paris VI) |
16 | * | 16 | * |
17 | * BSD ufs-inspired inode and directory allocation by | 17 | * BSD ufs-inspired inode and directory allocation by |
18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 | 18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 |
19 | * Big-endian to little-endian byte-swapping/bitmaps by | 19 | * Big-endian to little-endian byte-swapping/bitmaps by |
20 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 20 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
21 | * | 21 | * |
22 | * UFS2 write support added by | 22 | * UFS2 write support added by |
23 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | 23 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/ufs_fs.h> | 27 | #include <linux/ufs_fs.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/quotaops.h> | 31 | #include <linux/quotaops.h> |
32 | #include <linux/buffer_head.h> | 32 | #include <linux/buffer_head.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/bitops.h> | 34 | #include <linux/bitops.h> |
35 | #include <asm/byteorder.h> | 35 | #include <asm/byteorder.h> |
36 | 36 | ||
37 | #include "ufs.h" | ||
37 | #include "swab.h" | 38 | #include "swab.h" |
38 | #include "util.h" | 39 | #include "util.h" |
39 | 40 | ||
40 | /* | 41 | /* |
41 | * NOTE! When we get the inode, we're the only people | 42 | * NOTE! When we get the inode, we're the only people |
42 | * that have access to it, and as such there are no | 43 | * that have access to it, and as such there are no |
43 | * race conditions we have to worry about. The inode | 44 | * race conditions we have to worry about. The inode |
44 | * is not on the hash-lists, and it cannot be reached | 45 | * is not on the hash-lists, and it cannot be reached |
45 | * through the filesystem because the directory entry | 46 | * through the filesystem because the directory entry |
46 | * has been deleted earlier. | 47 | * has been deleted earlier. |
47 | * | 48 | * |
48 | * HOWEVER: we must make sure that we get no aliases, | 49 | * HOWEVER: we must make sure that we get no aliases, |
49 | * which means that we have to call "clear_inode()" | 50 | * which means that we have to call "clear_inode()" |
50 | * _before_ we mark the inode not in use in the inode | 51 | * _before_ we mark the inode not in use in the inode |
51 | * bitmaps. Otherwise a newly created file might use | 52 | * bitmaps. Otherwise a newly created file might use |
52 | * the same inode number (not actually the same pointer | 53 | * the same inode number (not actually the same pointer |
53 | * though), and then we'd have two inodes sharing the | 54 | * though), and then we'd have two inodes sharing the |
54 | * same inode number and space on the harddisk. | 55 | * same inode number and space on the harddisk. |
55 | */ | 56 | */ |
56 | void ufs_free_inode (struct inode * inode) | 57 | void ufs_free_inode (struct inode * inode) |
57 | { | 58 | { |
58 | struct super_block * sb; | 59 | struct super_block * sb; |
59 | struct ufs_sb_private_info * uspi; | 60 | struct ufs_sb_private_info * uspi; |
60 | struct ufs_super_block_first * usb1; | 61 | struct ufs_super_block_first * usb1; |
61 | struct ufs_cg_private_info * ucpi; | 62 | struct ufs_cg_private_info * ucpi; |
62 | struct ufs_cylinder_group * ucg; | 63 | struct ufs_cylinder_group * ucg; |
63 | int is_directory; | 64 | int is_directory; |
64 | unsigned ino, cg, bit; | 65 | unsigned ino, cg, bit; |
65 | 66 | ||
66 | UFSD("ENTER, ino %lu\n", inode->i_ino); | 67 | UFSD("ENTER, ino %lu\n", inode->i_ino); |
67 | 68 | ||
68 | sb = inode->i_sb; | 69 | sb = inode->i_sb; |
69 | uspi = UFS_SB(sb)->s_uspi; | 70 | uspi = UFS_SB(sb)->s_uspi; |
70 | usb1 = ubh_get_usb_first(uspi); | 71 | usb1 = ubh_get_usb_first(uspi); |
71 | 72 | ||
72 | ino = inode->i_ino; | 73 | ino = inode->i_ino; |
73 | 74 | ||
74 | lock_super (sb); | 75 | lock_super (sb); |
75 | 76 | ||
76 | if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { | 77 | if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { |
77 | ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); | 78 | ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); |
78 | unlock_super (sb); | 79 | unlock_super (sb); |
79 | return; | 80 | return; |
80 | } | 81 | } |
81 | 82 | ||
82 | cg = ufs_inotocg (ino); | 83 | cg = ufs_inotocg (ino); |
83 | bit = ufs_inotocgoff (ino); | 84 | bit = ufs_inotocgoff (ino); |
84 | ucpi = ufs_load_cylinder (sb, cg); | 85 | ucpi = ufs_load_cylinder (sb, cg); |
85 | if (!ucpi) { | 86 | if (!ucpi) { |
86 | unlock_super (sb); | 87 | unlock_super (sb); |
87 | return; | 88 | return; |
88 | } | 89 | } |
89 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 90 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
90 | if (!ufs_cg_chkmagic(sb, ucg)) | 91 | if (!ufs_cg_chkmagic(sb, ucg)) |
91 | ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number"); | 92 | ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number"); |
92 | 93 | ||
93 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); | 94 | ucg->cg_time = cpu_to_fs32(sb, get_seconds()); |
94 | 95 | ||
95 | is_directory = S_ISDIR(inode->i_mode); | 96 | is_directory = S_ISDIR(inode->i_mode); |
96 | 97 | ||
97 | DQUOT_FREE_INODE(inode); | 98 | DQUOT_FREE_INODE(inode); |
98 | DQUOT_DROP(inode); | 99 | DQUOT_DROP(inode); |
99 | 100 | ||
100 | clear_inode (inode); | 101 | clear_inode (inode); |
101 | 102 | ||
102 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) | 103 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) |
103 | ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino); | 104 | ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino); |
104 | else { | 105 | else { |
105 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 106 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); |
106 | if (ino < ucpi->c_irotor) | 107 | if (ino < ucpi->c_irotor) |
107 | ucpi->c_irotor = ino; | 108 | ucpi->c_irotor = ino; |
108 | fs32_add(sb, &ucg->cg_cs.cs_nifree, 1); | 109 | fs32_add(sb, &ucg->cg_cs.cs_nifree, 1); |
109 | uspi->cs_total.cs_nifree++; | 110 | uspi->cs_total.cs_nifree++; |
110 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1); | 111 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1); |
111 | 112 | ||
112 | if (is_directory) { | 113 | if (is_directory) { |
113 | fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1); | 114 | fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1); |
114 | uspi->cs_total.cs_ndir--; | 115 | uspi->cs_total.cs_ndir--; |
115 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1); | 116 | fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1); |
116 | } | 117 | } |
117 | } | 118 | } |
118 | 119 | ||
119 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 120 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
120 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 121 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
121 | if (sb->s_flags & MS_SYNCHRONOUS) { | 122 | if (sb->s_flags & MS_SYNCHRONOUS) { |
122 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 123 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
123 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 124 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
124 | } | 125 | } |
125 | 126 | ||
126 | sb->s_dirt = 1; | 127 | sb->s_dirt = 1; |
127 | unlock_super (sb); | 128 | unlock_super (sb); |
128 | UFSD("EXIT\n"); | 129 | UFSD("EXIT\n"); |
129 | } | 130 | } |
130 | 131 | ||
131 | /* | 132 | /* |
132 | * Nullify new chunk of inodes, | 133 | * Nullify new chunk of inodes, |
133 | * BSD people also set ui_gen field of inode | 134 | * BSD people also set ui_gen field of inode |
134 | * during nullification, but we not care about | 135 | * during nullification, but we not care about |
135 | * that because of linux ufs do not support NFS | 136 | * that because of linux ufs do not support NFS |
136 | */ | 137 | */ |
137 | static void ufs2_init_inodes_chunk(struct super_block *sb, | 138 | static void ufs2_init_inodes_chunk(struct super_block *sb, |
138 | struct ufs_cg_private_info *ucpi, | 139 | struct ufs_cg_private_info *ucpi, |
139 | struct ufs_cylinder_group *ucg) | 140 | struct ufs_cylinder_group *ucg) |
140 | { | 141 | { |
141 | struct buffer_head *bh; | 142 | struct buffer_head *bh; |
142 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 143 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
143 | sector_t beg = uspi->s_sbbase + | 144 | sector_t beg = uspi->s_sbbase + |
144 | ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + | 145 | ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + |
145 | fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); | 146 | fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); |
146 | sector_t end = beg + uspi->s_fpb; | 147 | sector_t end = beg + uspi->s_fpb; |
147 | 148 | ||
148 | UFSD("ENTER cgno %d\n", ucpi->c_cgx); | 149 | UFSD("ENTER cgno %d\n", ucpi->c_cgx); |
149 | 150 | ||
150 | for (; beg < end; ++beg) { | 151 | for (; beg < end; ++beg) { |
151 | bh = sb_getblk(sb, beg); | 152 | bh = sb_getblk(sb, beg); |
152 | lock_buffer(bh); | 153 | lock_buffer(bh); |
153 | memset(bh->b_data, 0, sb->s_blocksize); | 154 | memset(bh->b_data, 0, sb->s_blocksize); |
154 | set_buffer_uptodate(bh); | 155 | set_buffer_uptodate(bh); |
155 | mark_buffer_dirty(bh); | 156 | mark_buffer_dirty(bh); |
156 | unlock_buffer(bh); | 157 | unlock_buffer(bh); |
157 | if (sb->s_flags & MS_SYNCHRONOUS) | 158 | if (sb->s_flags & MS_SYNCHRONOUS) |
158 | sync_dirty_buffer(bh); | 159 | sync_dirty_buffer(bh); |
159 | brelse(bh); | 160 | brelse(bh); |
160 | } | 161 | } |
161 | 162 | ||
162 | fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); | 163 | fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); |
163 | ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); | 164 | ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); |
164 | if (sb->s_flags & MS_SYNCHRONOUS) { | 165 | if (sb->s_flags & MS_SYNCHRONOUS) { |
165 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 166 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
166 | ubh_wait_on_buffer(UCPI_UBH(ucpi)); | 167 | ubh_wait_on_buffer(UCPI_UBH(ucpi)); |
167 | } | 168 | } |
168 | 169 | ||
169 | UFSD("EXIT\n"); | 170 | UFSD("EXIT\n"); |
170 | } | 171 | } |
171 | 172 | ||
172 | /* | 173 | /* |
173 | * There are two policies for allocating an inode. If the new inode is | 174 | * There are two policies for allocating an inode. If the new inode is |
174 | * a directory, then a forward search is made for a block group with both | 175 | * a directory, then a forward search is made for a block group with both |
175 | * free space and a low directory-to-inode ratio; if that fails, then of | 176 | * free space and a low directory-to-inode ratio; if that fails, then of |
176 | * the groups with above-average free space, that group with the fewest | 177 | * the groups with above-average free space, that group with the fewest |
177 | * directories already is chosen. | 178 | * directories already is chosen. |
178 | * | 179 | * |
179 | * For other inodes, search forward from the parent directory's block | 180 | * For other inodes, search forward from the parent directory's block |
180 | * group to find a free inode. | 181 | * group to find a free inode. |
181 | */ | 182 | */ |
182 | struct inode * ufs_new_inode(struct inode * dir, int mode) | 183 | struct inode * ufs_new_inode(struct inode * dir, int mode) |
183 | { | 184 | { |
184 | struct super_block * sb; | 185 | struct super_block * sb; |
185 | struct ufs_sb_info * sbi; | 186 | struct ufs_sb_info * sbi; |
186 | struct ufs_sb_private_info * uspi; | 187 | struct ufs_sb_private_info * uspi; |
187 | struct ufs_super_block_first * usb1; | 188 | struct ufs_super_block_first * usb1; |
188 | struct ufs_cg_private_info * ucpi; | 189 | struct ufs_cg_private_info * ucpi; |
189 | struct ufs_cylinder_group * ucg; | 190 | struct ufs_cylinder_group * ucg; |
190 | struct inode * inode; | 191 | struct inode * inode; |
191 | unsigned cg, bit, i, j, start; | 192 | unsigned cg, bit, i, j, start; |
192 | struct ufs_inode_info *ufsi; | 193 | struct ufs_inode_info *ufsi; |
193 | int err = -ENOSPC; | 194 | int err = -ENOSPC; |
194 | 195 | ||
195 | UFSD("ENTER\n"); | 196 | UFSD("ENTER\n"); |
196 | 197 | ||
197 | /* Cannot create files in a deleted directory */ | 198 | /* Cannot create files in a deleted directory */ |
198 | if (!dir || !dir->i_nlink) | 199 | if (!dir || !dir->i_nlink) |
199 | return ERR_PTR(-EPERM); | 200 | return ERR_PTR(-EPERM); |
200 | sb = dir->i_sb; | 201 | sb = dir->i_sb; |
201 | inode = new_inode(sb); | 202 | inode = new_inode(sb); |
202 | if (!inode) | 203 | if (!inode) |
203 | return ERR_PTR(-ENOMEM); | 204 | return ERR_PTR(-ENOMEM); |
204 | ufsi = UFS_I(inode); | 205 | ufsi = UFS_I(inode); |
205 | sbi = UFS_SB(sb); | 206 | sbi = UFS_SB(sb); |
206 | uspi = sbi->s_uspi; | 207 | uspi = sbi->s_uspi; |
207 | usb1 = ubh_get_usb_first(uspi); | 208 | usb1 = ubh_get_usb_first(uspi); |
208 | 209 | ||
209 | lock_super (sb); | 210 | lock_super (sb); |
210 | 211 | ||
211 | /* | 212 | /* |
212 | * Try to place the inode in its parent directory | 213 | * Try to place the inode in its parent directory |
213 | */ | 214 | */ |
214 | i = ufs_inotocg(dir->i_ino); | 215 | i = ufs_inotocg(dir->i_ino); |
215 | if (sbi->fs_cs(i).cs_nifree) { | 216 | if (sbi->fs_cs(i).cs_nifree) { |
216 | cg = i; | 217 | cg = i; |
217 | goto cg_found; | 218 | goto cg_found; |
218 | } | 219 | } |
219 | 220 | ||
220 | /* | 221 | /* |
221 | * Use a quadratic hash to find a group with a free inode | 222 | * Use a quadratic hash to find a group with a free inode |
222 | */ | 223 | */ |
223 | for ( j = 1; j < uspi->s_ncg; j <<= 1 ) { | 224 | for ( j = 1; j < uspi->s_ncg; j <<= 1 ) { |
224 | i += j; | 225 | i += j; |
225 | if (i >= uspi->s_ncg) | 226 | if (i >= uspi->s_ncg) |
226 | i -= uspi->s_ncg; | 227 | i -= uspi->s_ncg; |
227 | if (sbi->fs_cs(i).cs_nifree) { | 228 | if (sbi->fs_cs(i).cs_nifree) { |
228 | cg = i; | 229 | cg = i; |
229 | goto cg_found; | 230 | goto cg_found; |
230 | } | 231 | } |
231 | } | 232 | } |
232 | 233 | ||
233 | /* | 234 | /* |
234 | * That failed: try linear search for a free inode | 235 | * That failed: try linear search for a free inode |
235 | */ | 236 | */ |
236 | i = ufs_inotocg(dir->i_ino) + 1; | 237 | i = ufs_inotocg(dir->i_ino) + 1; |
237 | for (j = 2; j < uspi->s_ncg; j++) { | 238 | for (j = 2; j < uspi->s_ncg; j++) { |
238 | i++; | 239 | i++; |
239 | if (i >= uspi->s_ncg) | 240 | if (i >= uspi->s_ncg) |
240 | i = 0; | 241 | i = 0; |
241 | if (sbi->fs_cs(i).cs_nifree) { | 242 | if (sbi->fs_cs(i).cs_nifree) { |
242 | cg = i; | 243 | cg = i; |
243 | goto cg_found; | 244 | goto cg_found; |
244 | } | 245 | } |
245 | } | 246 | } |
246 | 247 | ||
247 | goto failed; | 248 | goto failed; |
248 | 249 | ||
249 | cg_found: | 250 | cg_found: |
250 | ucpi = ufs_load_cylinder (sb, cg); | 251 | ucpi = ufs_load_cylinder (sb, cg); |
251 | if (!ucpi) { | 252 | if (!ucpi) { |
252 | err = -EIO; | 253 | err = -EIO; |
253 | goto failed; | 254 | goto failed; |
254 | } | 255 | } |
255 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 256 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
256 | if (!ufs_cg_chkmagic(sb, ucg)) | 257 | if (!ufs_cg_chkmagic(sb, ucg)) |
257 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); | 258 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); |
258 | 259 | ||
259 | start = ucpi->c_irotor; | 260 | start = ucpi->c_irotor; |
260 | bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start); | 261 | bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start); |
261 | if (!(bit < uspi->s_ipg)) { | 262 | if (!(bit < uspi->s_ipg)) { |
262 | bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start); | 263 | bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start); |
263 | if (!(bit < start)) { | 264 | if (!(bit < start)) { |
264 | ufs_error (sb, "ufs_new_inode", | 265 | ufs_error (sb, "ufs_new_inode", |
265 | "cylinder group %u corrupted - error in inode bitmap\n", cg); | 266 | "cylinder group %u corrupted - error in inode bitmap\n", cg); |
266 | err = -EIO; | 267 | err = -EIO; |
267 | goto failed; | 268 | goto failed; |
268 | } | 269 | } |
269 | } | 270 | } |
270 | UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg); | 271 | UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg); |
271 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) | 272 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) |
272 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 273 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); |
273 | else { | 274 | else { |
274 | ufs_panic (sb, "ufs_new_inode", "internal error"); | 275 | ufs_panic (sb, "ufs_new_inode", "internal error"); |
275 | err = -EIO; | 276 | err = -EIO; |
276 | goto failed; | 277 | goto failed; |
277 | } | 278 | } |
278 | 279 | ||
279 | if (uspi->fs_magic == UFS2_MAGIC) { | 280 | if (uspi->fs_magic == UFS2_MAGIC) { |
280 | u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); | 281 | u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); |
281 | 282 | ||
282 | if (bit + uspi->s_inopb > initediblk && | 283 | if (bit + uspi->s_inopb > initediblk && |
283 | initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) | 284 | initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) |
284 | ufs2_init_inodes_chunk(sb, ucpi, ucg); | 285 | ufs2_init_inodes_chunk(sb, ucpi, ucg); |
285 | } | 286 | } |
286 | 287 | ||
287 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); | 288 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); |
288 | uspi->cs_total.cs_nifree--; | 289 | uspi->cs_total.cs_nifree--; |
289 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); | 290 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); |
290 | 291 | ||
291 | if (S_ISDIR(mode)) { | 292 | if (S_ISDIR(mode)) { |
292 | fs32_add(sb, &ucg->cg_cs.cs_ndir, 1); | 293 | fs32_add(sb, &ucg->cg_cs.cs_ndir, 1); |
293 | uspi->cs_total.cs_ndir++; | 294 | uspi->cs_total.cs_ndir++; |
294 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); | 295 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); |
295 | } | 296 | } |
296 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 297 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
297 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 298 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
298 | if (sb->s_flags & MS_SYNCHRONOUS) { | 299 | if (sb->s_flags & MS_SYNCHRONOUS) { |
299 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 300 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); |
300 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 301 | ubh_wait_on_buffer (UCPI_UBH(ucpi)); |
301 | } | 302 | } |
302 | sb->s_dirt = 1; | 303 | sb->s_dirt = 1; |
303 | 304 | ||
304 | inode->i_ino = cg * uspi->s_ipg + bit; | 305 | inode->i_ino = cg * uspi->s_ipg + bit; |
305 | inode->i_mode = mode; | 306 | inode->i_mode = mode; |
306 | inode->i_uid = current->fsuid; | 307 | inode->i_uid = current->fsuid; |
307 | if (dir->i_mode & S_ISGID) { | 308 | if (dir->i_mode & S_ISGID) { |
308 | inode->i_gid = dir->i_gid; | 309 | inode->i_gid = dir->i_gid; |
309 | if (S_ISDIR(mode)) | 310 | if (S_ISDIR(mode)) |
310 | inode->i_mode |= S_ISGID; | 311 | inode->i_mode |= S_ISGID; |
311 | } else | 312 | } else |
312 | inode->i_gid = current->fsgid; | 313 | inode->i_gid = current->fsgid; |
313 | 314 | ||
314 | inode->i_blocks = 0; | 315 | inode->i_blocks = 0; |
315 | inode->i_generation = 0; | 316 | inode->i_generation = 0; |
316 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 317 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
317 | ufsi->i_flags = UFS_I(dir)->i_flags; | 318 | ufsi->i_flags = UFS_I(dir)->i_flags; |
318 | ufsi->i_lastfrag = 0; | 319 | ufsi->i_lastfrag = 0; |
319 | ufsi->i_shadow = 0; | 320 | ufsi->i_shadow = 0; |
320 | ufsi->i_osync = 0; | 321 | ufsi->i_osync = 0; |
321 | ufsi->i_oeftflag = 0; | 322 | ufsi->i_oeftflag = 0; |
322 | ufsi->i_dir_start_lookup = 0; | 323 | ufsi->i_dir_start_lookup = 0; |
323 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); | 324 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); |
324 | insert_inode_hash(inode); | 325 | insert_inode_hash(inode); |
325 | mark_inode_dirty(inode); | 326 | mark_inode_dirty(inode); |
326 | 327 | ||
327 | if (uspi->fs_magic == UFS2_MAGIC) { | 328 | if (uspi->fs_magic == UFS2_MAGIC) { |
328 | struct buffer_head *bh; | 329 | struct buffer_head *bh; |
329 | struct ufs2_inode *ufs2_inode; | 330 | struct ufs2_inode *ufs2_inode; |
330 | 331 | ||
331 | /* | 332 | /* |
332 | * setup birth date, we do it here because of there is no sense | 333 | * setup birth date, we do it here because of there is no sense |
333 | * to hold it in struct ufs_inode_info, and lose 64 bit | 334 | * to hold it in struct ufs_inode_info, and lose 64 bit |
334 | */ | 335 | */ |
335 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); | 336 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); |
336 | if (!bh) { | 337 | if (!bh) { |
337 | ufs_warning(sb, "ufs_read_inode", | 338 | ufs_warning(sb, "ufs_read_inode", |
338 | "unable to read inode %lu\n", | 339 | "unable to read inode %lu\n", |
339 | inode->i_ino); | 340 | inode->i_ino); |
340 | err = -EIO; | 341 | err = -EIO; |
341 | goto fail_remove_inode; | 342 | goto fail_remove_inode; |
342 | } | 343 | } |
343 | lock_buffer(bh); | 344 | lock_buffer(bh); |
344 | ufs2_inode = (struct ufs2_inode *)bh->b_data; | 345 | ufs2_inode = (struct ufs2_inode *)bh->b_data; |
345 | ufs2_inode += ufs_inotofsbo(inode->i_ino); | 346 | ufs2_inode += ufs_inotofsbo(inode->i_ino); |
346 | ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec); | 347 | ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec); |
347 | ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec); | 348 | ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec); |
348 | mark_buffer_dirty(bh); | 349 | mark_buffer_dirty(bh); |
349 | unlock_buffer(bh); | 350 | unlock_buffer(bh); |
350 | if (sb->s_flags & MS_SYNCHRONOUS) | 351 | if (sb->s_flags & MS_SYNCHRONOUS) |
351 | sync_dirty_buffer(bh); | 352 | sync_dirty_buffer(bh); |
352 | brelse(bh); | 353 | brelse(bh); |
353 | } | 354 | } |
354 | 355 | ||
355 | unlock_super (sb); | 356 | unlock_super (sb); |
356 | 357 | ||
357 | if (DQUOT_ALLOC_INODE(inode)) { | 358 | if (DQUOT_ALLOC_INODE(inode)) { |
358 | DQUOT_DROP(inode); | 359 | DQUOT_DROP(inode); |
359 | err = -EDQUOT; | 360 | err = -EDQUOT; |
360 | goto fail_without_unlock; | 361 | goto fail_without_unlock; |
361 | } | 362 | } |
362 | 363 | ||
363 | UFSD("allocating inode %lu\n", inode->i_ino); | 364 | UFSD("allocating inode %lu\n", inode->i_ino); |
364 | UFSD("EXIT\n"); | 365 | UFSD("EXIT\n"); |
365 | return inode; | 366 | return inode; |
366 | 367 | ||
367 | fail_remove_inode: | 368 | fail_remove_inode: |
368 | unlock_super(sb); | 369 | unlock_super(sb); |
369 | fail_without_unlock: | 370 | fail_without_unlock: |
370 | inode->i_flags |= S_NOQUOTA; | 371 | inode->i_flags |= S_NOQUOTA; |
371 | inode->i_nlink = 0; | 372 | inode->i_nlink = 0; |
372 | iput(inode); | 373 | iput(inode); |
373 | UFSD("EXIT (FAILED): err %d\n", err); | 374 | UFSD("EXIT (FAILED): err %d\n", err); |
374 | return ERR_PTR(err); | 375 | return ERR_PTR(err); |
375 | failed: | 376 | failed: |
376 | unlock_super (sb); | 377 | unlock_super (sb); |
377 | make_bad_inode(inode); | 378 | make_bad_inode(inode); |
378 | iput (inode); | 379 | iput (inode); |
379 | UFSD("EXIT (FAILED): err %d\n", err); | 380 | UFSD("EXIT (FAILED): err %d\n", err); |
380 | return ERR_PTR(err); | 381 | return ERR_PTR(err); |
381 | } | 382 | } |
382 | 383 |
fs/ufs/inode.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/inode.c | 2 | * linux/fs/ufs/inode.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * from | 8 | * from |
9 | * | 9 | * |
10 | * linux/fs/ext2/inode.c | 10 | * linux/fs/ext2/inode.c |
11 | * | 11 | * |
12 | * Copyright (C) 1992, 1993, 1994, 1995 | 12 | * Copyright (C) 1992, 1993, 1994, 1995 |
13 | * Remy Card (card@masi.ibp.fr) | 13 | * Remy Card (card@masi.ibp.fr) |
14 | * Laboratoire MASI - Institut Blaise Pascal | 14 | * Laboratoire MASI - Institut Blaise Pascal |
15 | * Universite Pierre et Marie Curie (Paris VI) | 15 | * Universite Pierre et Marie Curie (Paris VI) |
16 | * | 16 | * |
17 | * from | 17 | * from |
18 | * | 18 | * |
19 | * linux/fs/minix/inode.c | 19 | * linux/fs/minix/inode.c |
20 | * | 20 | * |
21 | * Copyright (C) 1991, 1992 Linus Torvalds | 21 | * Copyright (C) 1991, 1992 Linus Torvalds |
22 | * | 22 | * |
23 | * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 | 23 | * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 |
24 | * Big-endian to little-endian byte-swapping/bitmaps by | 24 | * Big-endian to little-endian byte-swapping/bitmaps by |
25 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 25 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | 29 | #include <asm/system.h> |
30 | 30 | ||
31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/ufs_fs.h> | 33 | #include <linux/ufs_fs.h> |
34 | #include <linux/time.h> | 34 | #include <linux/time.h> |
35 | #include <linux/stat.h> | 35 | #include <linux/stat.h> |
36 | #include <linux/string.h> | 36 | #include <linux/string.h> |
37 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
38 | #include <linux/smp_lock.h> | 38 | #include <linux/smp_lock.h> |
39 | #include <linux/buffer_head.h> | 39 | #include <linux/buffer_head.h> |
40 | 40 | ||
41 | #include "ufs.h" | ||
41 | #include "swab.h" | 42 | #include "swab.h" |
42 | #include "util.h" | 43 | #include "util.h" |
43 | 44 | ||
44 | static u64 ufs_frag_map(struct inode *inode, sector_t frag); | 45 | static u64 ufs_frag_map(struct inode *inode, sector_t frag); |
45 | 46 | ||
46 | static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4]) | 47 | static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4]) |
47 | { | 48 | { |
48 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | 49 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; |
49 | int ptrs = uspi->s_apb; | 50 | int ptrs = uspi->s_apb; |
50 | int ptrs_bits = uspi->s_apbshift; | 51 | int ptrs_bits = uspi->s_apbshift; |
51 | const long direct_blocks = UFS_NDADDR, | 52 | const long direct_blocks = UFS_NDADDR, |
52 | indirect_blocks = ptrs, | 53 | indirect_blocks = ptrs, |
53 | double_blocks = (1 << (ptrs_bits * 2)); | 54 | double_blocks = (1 << (ptrs_bits * 2)); |
54 | int n = 0; | 55 | int n = 0; |
55 | 56 | ||
56 | 57 | ||
57 | UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks); | 58 | UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks); |
58 | if (i_block < 0) { | 59 | if (i_block < 0) { |
59 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); | 60 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); |
60 | } else if (i_block < direct_blocks) { | 61 | } else if (i_block < direct_blocks) { |
61 | offsets[n++] = i_block; | 62 | offsets[n++] = i_block; |
62 | } else if ((i_block -= direct_blocks) < indirect_blocks) { | 63 | } else if ((i_block -= direct_blocks) < indirect_blocks) { |
63 | offsets[n++] = UFS_IND_BLOCK; | 64 | offsets[n++] = UFS_IND_BLOCK; |
64 | offsets[n++] = i_block; | 65 | offsets[n++] = i_block; |
65 | } else if ((i_block -= indirect_blocks) < double_blocks) { | 66 | } else if ((i_block -= indirect_blocks) < double_blocks) { |
66 | offsets[n++] = UFS_DIND_BLOCK; | 67 | offsets[n++] = UFS_DIND_BLOCK; |
67 | offsets[n++] = i_block >> ptrs_bits; | 68 | offsets[n++] = i_block >> ptrs_bits; |
68 | offsets[n++] = i_block & (ptrs - 1); | 69 | offsets[n++] = i_block & (ptrs - 1); |
69 | } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { | 70 | } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { |
70 | offsets[n++] = UFS_TIND_BLOCK; | 71 | offsets[n++] = UFS_TIND_BLOCK; |
71 | offsets[n++] = i_block >> (ptrs_bits * 2); | 72 | offsets[n++] = i_block >> (ptrs_bits * 2); |
72 | offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); | 73 | offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); |
73 | offsets[n++] = i_block & (ptrs - 1); | 74 | offsets[n++] = i_block & (ptrs - 1); |
74 | } else { | 75 | } else { |
75 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big"); | 76 | ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big"); |
76 | } | 77 | } |
77 | return n; | 78 | return n; |
78 | } | 79 | } |
79 | 80 | ||
80 | /* | 81 | /* |
81 | * Returns the location of the fragment from | 82 | * Returns the location of the fragment from |
82 | * the begining of the filesystem. | 83 | * the begining of the filesystem. |
83 | */ | 84 | */ |
84 | 85 | ||
85 | static u64 ufs_frag_map(struct inode *inode, sector_t frag) | 86 | static u64 ufs_frag_map(struct inode *inode, sector_t frag) |
86 | { | 87 | { |
87 | struct ufs_inode_info *ufsi = UFS_I(inode); | 88 | struct ufs_inode_info *ufsi = UFS_I(inode); |
88 | struct super_block *sb = inode->i_sb; | 89 | struct super_block *sb = inode->i_sb; |
89 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 90 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
90 | u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift; | 91 | u64 mask = (u64) uspi->s_apbmask>>uspi->s_fpbshift; |
91 | int shift = uspi->s_apbshift-uspi->s_fpbshift; | 92 | int shift = uspi->s_apbshift-uspi->s_fpbshift; |
92 | sector_t offsets[4], *p; | 93 | sector_t offsets[4], *p; |
93 | int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets); | 94 | int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets); |
94 | u64 ret = 0L; | 95 | u64 ret = 0L; |
95 | __fs32 block; | 96 | __fs32 block; |
96 | __fs64 u2_block = 0L; | 97 | __fs64 u2_block = 0L; |
97 | unsigned flags = UFS_SB(sb)->s_flags; | 98 | unsigned flags = UFS_SB(sb)->s_flags; |
98 | u64 temp = 0L; | 99 | u64 temp = 0L; |
99 | 100 | ||
100 | UFSD(": frag = %llu depth = %d\n", (unsigned long long)frag, depth); | 101 | UFSD(": frag = %llu depth = %d\n", (unsigned long long)frag, depth); |
101 | UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n", | 102 | UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n", |
102 | uspi->s_fpbshift, uspi->s_apbmask, | 103 | uspi->s_fpbshift, uspi->s_apbmask, |
103 | (unsigned long long)mask); | 104 | (unsigned long long)mask); |
104 | 105 | ||
105 | if (depth == 0) | 106 | if (depth == 0) |
106 | return 0; | 107 | return 0; |
107 | 108 | ||
108 | p = offsets; | 109 | p = offsets; |
109 | 110 | ||
110 | lock_kernel(); | 111 | lock_kernel(); |
111 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) | 112 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
112 | goto ufs2; | 113 | goto ufs2; |
113 | 114 | ||
114 | block = ufsi->i_u1.i_data[*p++]; | 115 | block = ufsi->i_u1.i_data[*p++]; |
115 | if (!block) | 116 | if (!block) |
116 | goto out; | 117 | goto out; |
117 | while (--depth) { | 118 | while (--depth) { |
118 | struct buffer_head *bh; | 119 | struct buffer_head *bh; |
119 | sector_t n = *p++; | 120 | sector_t n = *p++; |
120 | 121 | ||
121 | bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift)); | 122 | bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift)); |
122 | if (!bh) | 123 | if (!bh) |
123 | goto out; | 124 | goto out; |
124 | block = ((__fs32 *) bh->b_data)[n & mask]; | 125 | block = ((__fs32 *) bh->b_data)[n & mask]; |
125 | brelse (bh); | 126 | brelse (bh); |
126 | if (!block) | 127 | if (!block) |
127 | goto out; | 128 | goto out; |
128 | } | 129 | } |
129 | ret = (u64) (uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask)); | 130 | ret = (u64) (uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask)); |
130 | goto out; | 131 | goto out; |
131 | ufs2: | 132 | ufs2: |
132 | u2_block = ufsi->i_u1.u2_i_data[*p++]; | 133 | u2_block = ufsi->i_u1.u2_i_data[*p++]; |
133 | if (!u2_block) | 134 | if (!u2_block) |
134 | goto out; | 135 | goto out; |
135 | 136 | ||
136 | 137 | ||
137 | while (--depth) { | 138 | while (--depth) { |
138 | struct buffer_head *bh; | 139 | struct buffer_head *bh; |
139 | sector_t n = *p++; | 140 | sector_t n = *p++; |
140 | 141 | ||
141 | 142 | ||
142 | temp = (u64)(uspi->s_sbbase) + fs64_to_cpu(sb, u2_block); | 143 | temp = (u64)(uspi->s_sbbase) + fs64_to_cpu(sb, u2_block); |
143 | bh = sb_bread(sb, temp +(u64) (n>>shift)); | 144 | bh = sb_bread(sb, temp +(u64) (n>>shift)); |
144 | if (!bh) | 145 | if (!bh) |
145 | goto out; | 146 | goto out; |
146 | u2_block = ((__fs64 *)bh->b_data)[n & mask]; | 147 | u2_block = ((__fs64 *)bh->b_data)[n & mask]; |
147 | brelse(bh); | 148 | brelse(bh); |
148 | if (!u2_block) | 149 | if (!u2_block) |
149 | goto out; | 150 | goto out; |
150 | } | 151 | } |
151 | temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block); | 152 | temp = (u64)uspi->s_sbbase + fs64_to_cpu(sb, u2_block); |
152 | ret = temp + (u64) (frag & uspi->s_fpbmask); | 153 | ret = temp + (u64) (frag & uspi->s_fpbmask); |
153 | 154 | ||
154 | out: | 155 | out: |
155 | unlock_kernel(); | 156 | unlock_kernel(); |
156 | return ret; | 157 | return ret; |
157 | } | 158 | } |
158 | 159 | ||
159 | /** | 160 | /** |
160 | * ufs_inode_getfrag() - allocate new fragment(s) | 161 | * ufs_inode_getfrag() - allocate new fragment(s) |
161 | * @inode - pointer to inode | 162 | * @inode - pointer to inode |
162 | * @fragment - number of `fragment' which hold pointer | 163 | * @fragment - number of `fragment' which hold pointer |
163 | * to new allocated fragment(s) | 164 | * to new allocated fragment(s) |
164 | * @new_fragment - number of new allocated fragment(s) | 165 | * @new_fragment - number of new allocated fragment(s) |
165 | * @required - how many fragment(s) we require | 166 | * @required - how many fragment(s) we require |
166 | * @err - we set it if something wrong | 167 | * @err - we set it if something wrong |
167 | * @phys - pointer to where we save physical number of new allocated fragments, | 168 | * @phys - pointer to where we save physical number of new allocated fragments, |
168 | * NULL if we allocate not data(indirect blocks for example). | 169 | * NULL if we allocate not data(indirect blocks for example). |
169 | * @new - we set it if we allocate new block | 170 | * @new - we set it if we allocate new block |
170 | * @locked_page - for ufs_new_fragments() | 171 | * @locked_page - for ufs_new_fragments() |
171 | */ | 172 | */ |
172 | static struct buffer_head * | 173 | static struct buffer_head * |
173 | ufs_inode_getfrag(struct inode *inode, u64 fragment, | 174 | ufs_inode_getfrag(struct inode *inode, u64 fragment, |
174 | sector_t new_fragment, unsigned int required, int *err, | 175 | sector_t new_fragment, unsigned int required, int *err, |
175 | long *phys, int *new, struct page *locked_page) | 176 | long *phys, int *new, struct page *locked_page) |
176 | { | 177 | { |
177 | struct ufs_inode_info *ufsi = UFS_I(inode); | 178 | struct ufs_inode_info *ufsi = UFS_I(inode); |
178 | struct super_block *sb = inode->i_sb; | 179 | struct super_block *sb = inode->i_sb; |
179 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 180 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
180 | struct buffer_head * result; | 181 | struct buffer_head * result; |
181 | unsigned blockoff, lastblockoff; | 182 | unsigned blockoff, lastblockoff; |
182 | u64 tmp, goal, lastfrag, block, lastblock; | 183 | u64 tmp, goal, lastfrag, block, lastblock; |
183 | void *p, *p2; | 184 | void *p, *p2; |
184 | 185 | ||
185 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, " | 186 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, " |
186 | "metadata %d\n", inode->i_ino, (unsigned long long)fragment, | 187 | "metadata %d\n", inode->i_ino, (unsigned long long)fragment, |
187 | (unsigned long long)new_fragment, required, !phys); | 188 | (unsigned long long)new_fragment, required, !phys); |
188 | 189 | ||
189 | /* TODO : to be done for write support | 190 | /* TODO : to be done for write support |
190 | if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) | 191 | if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
191 | goto ufs2; | 192 | goto ufs2; |
192 | */ | 193 | */ |
193 | 194 | ||
194 | block = ufs_fragstoblks (fragment); | 195 | block = ufs_fragstoblks (fragment); |
195 | blockoff = ufs_fragnum (fragment); | 196 | blockoff = ufs_fragnum (fragment); |
196 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); | 197 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); |
197 | 198 | ||
198 | goal = 0; | 199 | goal = 0; |
199 | 200 | ||
200 | repeat: | 201 | repeat: |
201 | tmp = ufs_data_ptr_to_cpu(sb, p); | 202 | tmp = ufs_data_ptr_to_cpu(sb, p); |
202 | 203 | ||
203 | lastfrag = ufsi->i_lastfrag; | 204 | lastfrag = ufsi->i_lastfrag; |
204 | if (tmp && fragment < lastfrag) { | 205 | if (tmp && fragment < lastfrag) { |
205 | if (!phys) { | 206 | if (!phys) { |
206 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 207 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
207 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) { | 208 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) { |
208 | UFSD("EXIT, result %llu\n", | 209 | UFSD("EXIT, result %llu\n", |
209 | (unsigned long long)tmp + blockoff); | 210 | (unsigned long long)tmp + blockoff); |
210 | return result; | 211 | return result; |
211 | } | 212 | } |
212 | brelse (result); | 213 | brelse (result); |
213 | goto repeat; | 214 | goto repeat; |
214 | } else { | 215 | } else { |
215 | *phys = uspi->s_sbbase + tmp + blockoff; | 216 | *phys = uspi->s_sbbase + tmp + blockoff; |
216 | return NULL; | 217 | return NULL; |
217 | } | 218 | } |
218 | } | 219 | } |
219 | 220 | ||
220 | lastblock = ufs_fragstoblks (lastfrag); | 221 | lastblock = ufs_fragstoblks (lastfrag); |
221 | lastblockoff = ufs_fragnum (lastfrag); | 222 | lastblockoff = ufs_fragnum (lastfrag); |
222 | /* | 223 | /* |
223 | * We will extend file into new block beyond last allocated block | 224 | * We will extend file into new block beyond last allocated block |
224 | */ | 225 | */ |
225 | if (lastblock < block) { | 226 | if (lastblock < block) { |
226 | /* | 227 | /* |
227 | * We must reallocate last allocated block | 228 | * We must reallocate last allocated block |
228 | */ | 229 | */ |
229 | if (lastblockoff) { | 230 | if (lastblockoff) { |
230 | p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock); | 231 | p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock); |
231 | tmp = ufs_new_fragments(inode, p2, lastfrag, | 232 | tmp = ufs_new_fragments(inode, p2, lastfrag, |
232 | ufs_data_ptr_to_cpu(sb, p2), | 233 | ufs_data_ptr_to_cpu(sb, p2), |
233 | uspi->s_fpb - lastblockoff, | 234 | uspi->s_fpb - lastblockoff, |
234 | err, locked_page); | 235 | err, locked_page); |
235 | if (!tmp) { | 236 | if (!tmp) { |
236 | if (lastfrag != ufsi->i_lastfrag) | 237 | if (lastfrag != ufsi->i_lastfrag) |
237 | goto repeat; | 238 | goto repeat; |
238 | else | 239 | else |
239 | return NULL; | 240 | return NULL; |
240 | } | 241 | } |
241 | lastfrag = ufsi->i_lastfrag; | 242 | lastfrag = ufsi->i_lastfrag; |
242 | 243 | ||
243 | } | 244 | } |
244 | tmp = ufs_data_ptr_to_cpu(sb, | 245 | tmp = ufs_data_ptr_to_cpu(sb, |
245 | ufs_get_direct_data_ptr(uspi, ufsi, | 246 | ufs_get_direct_data_ptr(uspi, ufsi, |
246 | lastblock)); | 247 | lastblock)); |
247 | if (tmp) | 248 | if (tmp) |
248 | goal = tmp + uspi->s_fpb; | 249 | goal = tmp + uspi->s_fpb; |
249 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, | 250 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, |
250 | goal, required + blockoff, | 251 | goal, required + blockoff, |
251 | err, | 252 | err, |
252 | phys != NULL ? locked_page : NULL); | 253 | phys != NULL ? locked_page : NULL); |
253 | } else if (lastblock == block) { | 254 | } else if (lastblock == block) { |
254 | /* | 255 | /* |
255 | * We will extend last allocated block | 256 | * We will extend last allocated block |
256 | */ | 257 | */ |
257 | tmp = ufs_new_fragments(inode, p, fragment - | 258 | tmp = ufs_new_fragments(inode, p, fragment - |
258 | (blockoff - lastblockoff), | 259 | (blockoff - lastblockoff), |
259 | ufs_data_ptr_to_cpu(sb, p), | 260 | ufs_data_ptr_to_cpu(sb, p), |
260 | required + (blockoff - lastblockoff), | 261 | required + (blockoff - lastblockoff), |
261 | err, phys != NULL ? locked_page : NULL); | 262 | err, phys != NULL ? locked_page : NULL); |
262 | } else /* (lastblock > block) */ { | 263 | } else /* (lastblock > block) */ { |
263 | /* | 264 | /* |
264 | * We will allocate new block before last allocated block | 265 | * We will allocate new block before last allocated block |
265 | */ | 266 | */ |
266 | if (block) { | 267 | if (block) { |
267 | tmp = ufs_data_ptr_to_cpu(sb, | 268 | tmp = ufs_data_ptr_to_cpu(sb, |
268 | ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); | 269 | ufs_get_direct_data_ptr(uspi, ufsi, block - 1)); |
269 | if (tmp) | 270 | if (tmp) |
270 | goal = tmp + uspi->s_fpb; | 271 | goal = tmp + uspi->s_fpb; |
271 | } | 272 | } |
272 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, | 273 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, |
273 | goal, uspi->s_fpb, err, | 274 | goal, uspi->s_fpb, err, |
274 | phys != NULL ? locked_page : NULL); | 275 | phys != NULL ? locked_page : NULL); |
275 | } | 276 | } |
276 | if (!tmp) { | 277 | if (!tmp) { |
277 | if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) || | 278 | if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) || |
278 | (blockoff && lastfrag != ufsi->i_lastfrag)) | 279 | (blockoff && lastfrag != ufsi->i_lastfrag)) |
279 | goto repeat; | 280 | goto repeat; |
280 | *err = -ENOSPC; | 281 | *err = -ENOSPC; |
281 | return NULL; | 282 | return NULL; |
282 | } | 283 | } |
283 | 284 | ||
284 | if (!phys) { | 285 | if (!phys) { |
285 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 286 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
286 | } else { | 287 | } else { |
287 | *phys = uspi->s_sbbase + tmp + blockoff; | 288 | *phys = uspi->s_sbbase + tmp + blockoff; |
288 | result = NULL; | 289 | result = NULL; |
289 | *err = 0; | 290 | *err = 0; |
290 | *new = 1; | 291 | *new = 1; |
291 | } | 292 | } |
292 | 293 | ||
293 | inode->i_ctime = CURRENT_TIME_SEC; | 294 | inode->i_ctime = CURRENT_TIME_SEC; |
294 | if (IS_SYNC(inode)) | 295 | if (IS_SYNC(inode)) |
295 | ufs_sync_inode (inode); | 296 | ufs_sync_inode (inode); |
296 | mark_inode_dirty(inode); | 297 | mark_inode_dirty(inode); |
297 | UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff); | 298 | UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff); |
298 | return result; | 299 | return result; |
299 | 300 | ||
300 | /* This part : To be implemented .... | 301 | /* This part : To be implemented .... |
301 | Required only for writing, not required for READ-ONLY. | 302 | Required only for writing, not required for READ-ONLY. |
302 | ufs2: | 303 | ufs2: |
303 | 304 | ||
304 | u2_block = ufs_fragstoblks(fragment); | 305 | u2_block = ufs_fragstoblks(fragment); |
305 | u2_blockoff = ufs_fragnum(fragment); | 306 | u2_blockoff = ufs_fragnum(fragment); |
306 | p = ufsi->i_u1.u2_i_data + block; | 307 | p = ufsi->i_u1.u2_i_data + block; |
307 | goal = 0; | 308 | goal = 0; |
308 | 309 | ||
309 | repeat2: | 310 | repeat2: |
310 | tmp = fs32_to_cpu(sb, *p); | 311 | tmp = fs32_to_cpu(sb, *p); |
311 | lastfrag = ufsi->i_lastfrag; | 312 | lastfrag = ufsi->i_lastfrag; |
312 | 313 | ||
313 | */ | 314 | */ |
314 | } | 315 | } |
315 | 316 | ||
316 | /** | 317 | /** |
317 | * ufs_inode_getblock() - allocate new block | 318 | * ufs_inode_getblock() - allocate new block |
318 | * @inode - pointer to inode | 319 | * @inode - pointer to inode |
319 | * @bh - pointer to block which hold "pointer" to new allocated block | 320 | * @bh - pointer to block which hold "pointer" to new allocated block |
320 | * @fragment - number of `fragment' which hold pointer | 321 | * @fragment - number of `fragment' which hold pointer |
321 | * to new allocated block | 322 | * to new allocated block |
322 | * @new_fragment - number of new allocated fragment | 323 | * @new_fragment - number of new allocated fragment |
323 | * (block will hold this fragment and also uspi->s_fpb-1) | 324 | * (block will hold this fragment and also uspi->s_fpb-1) |
324 | * @err - see ufs_inode_getfrag() | 325 | * @err - see ufs_inode_getfrag() |
325 | * @phys - see ufs_inode_getfrag() | 326 | * @phys - see ufs_inode_getfrag() |
326 | * @new - see ufs_inode_getfrag() | 327 | * @new - see ufs_inode_getfrag() |
327 | * @locked_page - see ufs_inode_getfrag() | 328 | * @locked_page - see ufs_inode_getfrag() |
328 | */ | 329 | */ |
329 | static struct buffer_head * | 330 | static struct buffer_head * |
330 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, | 331 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, |
331 | u64 fragment, sector_t new_fragment, int *err, | 332 | u64 fragment, sector_t new_fragment, int *err, |
332 | long *phys, int *new, struct page *locked_page) | 333 | long *phys, int *new, struct page *locked_page) |
333 | { | 334 | { |
334 | struct super_block *sb = inode->i_sb; | 335 | struct super_block *sb = inode->i_sb; |
335 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 336 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
336 | struct buffer_head * result; | 337 | struct buffer_head * result; |
337 | unsigned blockoff; | 338 | unsigned blockoff; |
338 | u64 tmp, goal, block; | 339 | u64 tmp, goal, block; |
339 | void *p; | 340 | void *p; |
340 | 341 | ||
341 | block = ufs_fragstoblks (fragment); | 342 | block = ufs_fragstoblks (fragment); |
342 | blockoff = ufs_fragnum (fragment); | 343 | blockoff = ufs_fragnum (fragment); |
343 | 344 | ||
344 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n", | 345 | UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n", |
345 | inode->i_ino, (unsigned long long)fragment, | 346 | inode->i_ino, (unsigned long long)fragment, |
346 | (unsigned long long)new_fragment, !phys); | 347 | (unsigned long long)new_fragment, !phys); |
347 | 348 | ||
348 | result = NULL; | 349 | result = NULL; |
349 | if (!bh) | 350 | if (!bh) |
350 | goto out; | 351 | goto out; |
351 | if (!buffer_uptodate(bh)) { | 352 | if (!buffer_uptodate(bh)) { |
352 | ll_rw_block (READ, 1, &bh); | 353 | ll_rw_block (READ, 1, &bh); |
353 | wait_on_buffer (bh); | 354 | wait_on_buffer (bh); |
354 | if (!buffer_uptodate(bh)) | 355 | if (!buffer_uptodate(bh)) |
355 | goto out; | 356 | goto out; |
356 | } | 357 | } |
357 | if (uspi->fs_magic == UFS2_MAGIC) | 358 | if (uspi->fs_magic == UFS2_MAGIC) |
358 | p = (__fs64 *)bh->b_data + block; | 359 | p = (__fs64 *)bh->b_data + block; |
359 | else | 360 | else |
360 | p = (__fs32 *)bh->b_data + block; | 361 | p = (__fs32 *)bh->b_data + block; |
361 | repeat: | 362 | repeat: |
362 | tmp = ufs_data_ptr_to_cpu(sb, p); | 363 | tmp = ufs_data_ptr_to_cpu(sb, p); |
363 | if (tmp) { | 364 | if (tmp) { |
364 | if (!phys) { | 365 | if (!phys) { |
365 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 366 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
366 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) | 367 | if (tmp == ufs_data_ptr_to_cpu(sb, p)) |
367 | goto out; | 368 | goto out; |
368 | brelse (result); | 369 | brelse (result); |
369 | goto repeat; | 370 | goto repeat; |
370 | } else { | 371 | } else { |
371 | *phys = uspi->s_sbbase + tmp + blockoff; | 372 | *phys = uspi->s_sbbase + tmp + blockoff; |
372 | goto out; | 373 | goto out; |
373 | } | 374 | } |
374 | } | 375 | } |
375 | 376 | ||
376 | if (block && (uspi->fs_magic == UFS2_MAGIC ? | 377 | if (block && (uspi->fs_magic == UFS2_MAGIC ? |
377 | (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) : | 378 | (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) : |
378 | (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1])))) | 379 | (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1])))) |
379 | goal = tmp + uspi->s_fpb; | 380 | goal = tmp + uspi->s_fpb; |
380 | else | 381 | else |
381 | goal = bh->b_blocknr + uspi->s_fpb; | 382 | goal = bh->b_blocknr + uspi->s_fpb; |
382 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, | 383 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal, |
383 | uspi->s_fpb, err, locked_page); | 384 | uspi->s_fpb, err, locked_page); |
384 | if (!tmp) { | 385 | if (!tmp) { |
385 | if (ufs_data_ptr_to_cpu(sb, p)) | 386 | if (ufs_data_ptr_to_cpu(sb, p)) |
386 | goto repeat; | 387 | goto repeat; |
387 | goto out; | 388 | goto out; |
388 | } | 389 | } |
389 | 390 | ||
390 | 391 | ||
391 | if (!phys) { | 392 | if (!phys) { |
392 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); | 393 | result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); |
393 | } else { | 394 | } else { |
394 | *phys = uspi->s_sbbase + tmp + blockoff; | 395 | *phys = uspi->s_sbbase + tmp + blockoff; |
395 | *new = 1; | 396 | *new = 1; |
396 | } | 397 | } |
397 | 398 | ||
398 | mark_buffer_dirty(bh); | 399 | mark_buffer_dirty(bh); |
399 | if (IS_SYNC(inode)) | 400 | if (IS_SYNC(inode)) |
400 | sync_dirty_buffer(bh); | 401 | sync_dirty_buffer(bh); |
401 | inode->i_ctime = CURRENT_TIME_SEC; | 402 | inode->i_ctime = CURRENT_TIME_SEC; |
402 | mark_inode_dirty(inode); | 403 | mark_inode_dirty(inode); |
403 | UFSD("result %llu\n", (unsigned long long)tmp + blockoff); | 404 | UFSD("result %llu\n", (unsigned long long)tmp + blockoff); |
404 | out: | 405 | out: |
405 | brelse (bh); | 406 | brelse (bh); |
406 | UFSD("EXIT\n"); | 407 | UFSD("EXIT\n"); |
407 | return result; | 408 | return result; |
408 | } | 409 | } |
409 | 410 | ||
410 | /** | 411 | /** |
411 | * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and | 412 | * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and |
412 | * readpage, writepage and so on | 413 | * readpage, writepage and so on |
413 | */ | 414 | */ |
414 | 415 | ||
415 | int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) | 416 | int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) |
416 | { | 417 | { |
417 | struct super_block * sb = inode->i_sb; | 418 | struct super_block * sb = inode->i_sb; |
418 | struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; | 419 | struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; |
419 | struct buffer_head * bh; | 420 | struct buffer_head * bh; |
420 | int ret, err, new; | 421 | int ret, err, new; |
421 | unsigned long ptr,phys; | 422 | unsigned long ptr,phys; |
422 | u64 phys64 = 0; | 423 | u64 phys64 = 0; |
423 | 424 | ||
424 | if (!create) { | 425 | if (!create) { |
425 | phys64 = ufs_frag_map(inode, fragment); | 426 | phys64 = ufs_frag_map(inode, fragment); |
426 | UFSD("phys64 = %llu\n", (unsigned long long)phys64); | 427 | UFSD("phys64 = %llu\n", (unsigned long long)phys64); |
427 | if (phys64) | 428 | if (phys64) |
428 | map_bh(bh_result, sb, phys64); | 429 | map_bh(bh_result, sb, phys64); |
429 | return 0; | 430 | return 0; |
430 | } | 431 | } |
431 | 432 | ||
432 | /* This code entered only while writing ....? */ | 433 | /* This code entered only while writing ....? */ |
433 | 434 | ||
434 | err = -EIO; | 435 | err = -EIO; |
435 | new = 0; | 436 | new = 0; |
436 | ret = 0; | 437 | ret = 0; |
437 | bh = NULL; | 438 | bh = NULL; |
438 | 439 | ||
439 | lock_kernel(); | 440 | lock_kernel(); |
440 | 441 | ||
441 | UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment); | 442 | UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment); |
442 | if (fragment < 0) | 443 | if (fragment < 0) |
443 | goto abort_negative; | 444 | goto abort_negative; |
444 | if (fragment > | 445 | if (fragment > |
445 | ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) | 446 | ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) |
446 | << uspi->s_fpbshift)) | 447 | << uspi->s_fpbshift)) |
447 | goto abort_too_big; | 448 | goto abort_too_big; |
448 | 449 | ||
449 | err = 0; | 450 | err = 0; |
450 | ptr = fragment; | 451 | ptr = fragment; |
451 | 452 | ||
452 | /* | 453 | /* |
453 | * ok, these macros clean the logic up a bit and make | 454 | * ok, these macros clean the logic up a bit and make |
454 | * it much more readable: | 455 | * it much more readable: |
455 | */ | 456 | */ |
456 | #define GET_INODE_DATABLOCK(x) \ | 457 | #define GET_INODE_DATABLOCK(x) \ |
457 | ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\ | 458 | ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\ |
458 | bh_result->b_page) | 459 | bh_result->b_page) |
459 | #define GET_INODE_PTR(x) \ | 460 | #define GET_INODE_PTR(x) \ |
460 | ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\ | 461 | ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\ |
461 | bh_result->b_page) | 462 | bh_result->b_page) |
462 | #define GET_INDIRECT_DATABLOCK(x) \ | 463 | #define GET_INDIRECT_DATABLOCK(x) \ |
463 | ufs_inode_getblock(inode, bh, x, fragment, \ | 464 | ufs_inode_getblock(inode, bh, x, fragment, \ |
464 | &err, &phys, &new, bh_result->b_page) | 465 | &err, &phys, &new, bh_result->b_page) |
465 | #define GET_INDIRECT_PTR(x) \ | 466 | #define GET_INDIRECT_PTR(x) \ |
466 | ufs_inode_getblock(inode, bh, x, fragment, \ | 467 | ufs_inode_getblock(inode, bh, x, fragment, \ |
467 | &err, NULL, NULL, NULL) | 468 | &err, NULL, NULL, NULL) |
468 | 469 | ||
469 | if (ptr < UFS_NDIR_FRAGMENT) { | 470 | if (ptr < UFS_NDIR_FRAGMENT) { |
470 | bh = GET_INODE_DATABLOCK(ptr); | 471 | bh = GET_INODE_DATABLOCK(ptr); |
471 | goto out; | 472 | goto out; |
472 | } | 473 | } |
473 | ptr -= UFS_NDIR_FRAGMENT; | 474 | ptr -= UFS_NDIR_FRAGMENT; |
474 | if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) { | 475 | if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) { |
475 | bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift)); | 476 | bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift)); |
476 | goto get_indirect; | 477 | goto get_indirect; |
477 | } | 478 | } |
478 | ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift); | 479 | ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift); |
479 | if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) { | 480 | if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) { |
480 | bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift)); | 481 | bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift)); |
481 | goto get_double; | 482 | goto get_double; |
482 | } | 483 | } |
483 | ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift); | 484 | ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift); |
484 | bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift)); | 485 | bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift)); |
485 | bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask); | 486 | bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask); |
486 | get_double: | 487 | get_double: |
487 | bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask); | 488 | bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask); |
488 | get_indirect: | 489 | get_indirect: |
489 | bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask); | 490 | bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask); |
490 | 491 | ||
491 | #undef GET_INODE_DATABLOCK | 492 | #undef GET_INODE_DATABLOCK |
492 | #undef GET_INODE_PTR | 493 | #undef GET_INODE_PTR |
493 | #undef GET_INDIRECT_DATABLOCK | 494 | #undef GET_INDIRECT_DATABLOCK |
494 | #undef GET_INDIRECT_PTR | 495 | #undef GET_INDIRECT_PTR |
495 | 496 | ||
496 | out: | 497 | out: |
497 | if (err) | 498 | if (err) |
498 | goto abort; | 499 | goto abort; |
499 | if (new) | 500 | if (new) |
500 | set_buffer_new(bh_result); | 501 | set_buffer_new(bh_result); |
501 | map_bh(bh_result, sb, phys); | 502 | map_bh(bh_result, sb, phys); |
502 | abort: | 503 | abort: |
503 | unlock_kernel(); | 504 | unlock_kernel(); |
504 | return err; | 505 | return err; |
505 | 506 | ||
506 | abort_negative: | 507 | abort_negative: |
507 | ufs_warning(sb, "ufs_get_block", "block < 0"); | 508 | ufs_warning(sb, "ufs_get_block", "block < 0"); |
508 | goto abort; | 509 | goto abort; |
509 | 510 | ||
510 | abort_too_big: | 511 | abort_too_big: |
511 | ufs_warning(sb, "ufs_get_block", "block > big"); | 512 | ufs_warning(sb, "ufs_get_block", "block > big"); |
512 | goto abort; | 513 | goto abort; |
513 | } | 514 | } |
514 | 515 | ||
515 | static struct buffer_head *ufs_getfrag(struct inode *inode, | 516 | static struct buffer_head *ufs_getfrag(struct inode *inode, |
516 | unsigned int fragment, | 517 | unsigned int fragment, |
517 | int create, int *err) | 518 | int create, int *err) |
518 | { | 519 | { |
519 | struct buffer_head dummy; | 520 | struct buffer_head dummy; |
520 | int error; | 521 | int error; |
521 | 522 | ||
522 | dummy.b_state = 0; | 523 | dummy.b_state = 0; |
523 | dummy.b_blocknr = -1000; | 524 | dummy.b_blocknr = -1000; |
524 | error = ufs_getfrag_block(inode, fragment, &dummy, create); | 525 | error = ufs_getfrag_block(inode, fragment, &dummy, create); |
525 | *err = error; | 526 | *err = error; |
526 | if (!error && buffer_mapped(&dummy)) { | 527 | if (!error && buffer_mapped(&dummy)) { |
527 | struct buffer_head *bh; | 528 | struct buffer_head *bh; |
528 | bh = sb_getblk(inode->i_sb, dummy.b_blocknr); | 529 | bh = sb_getblk(inode->i_sb, dummy.b_blocknr); |
529 | if (buffer_new(&dummy)) { | 530 | if (buffer_new(&dummy)) { |
530 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); | 531 | memset(bh->b_data, 0, inode->i_sb->s_blocksize); |
531 | set_buffer_uptodate(bh); | 532 | set_buffer_uptodate(bh); |
532 | mark_buffer_dirty(bh); | 533 | mark_buffer_dirty(bh); |
533 | } | 534 | } |
534 | return bh; | 535 | return bh; |
535 | } | 536 | } |
536 | return NULL; | 537 | return NULL; |
537 | } | 538 | } |
538 | 539 | ||
539 | struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, | 540 | struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, |
540 | int create, int * err) | 541 | int create, int * err) |
541 | { | 542 | { |
542 | struct buffer_head * bh; | 543 | struct buffer_head * bh; |
543 | 544 | ||
544 | UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment); | 545 | UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment); |
545 | bh = ufs_getfrag (inode, fragment, create, err); | 546 | bh = ufs_getfrag (inode, fragment, create, err); |
546 | if (!bh || buffer_uptodate(bh)) | 547 | if (!bh || buffer_uptodate(bh)) |
547 | return bh; | 548 | return bh; |
548 | ll_rw_block (READ, 1, &bh); | 549 | ll_rw_block (READ, 1, &bh); |
549 | wait_on_buffer (bh); | 550 | wait_on_buffer (bh); |
550 | if (buffer_uptodate(bh)) | 551 | if (buffer_uptodate(bh)) |
551 | return bh; | 552 | return bh; |
552 | brelse (bh); | 553 | brelse (bh); |
553 | *err = -EIO; | 554 | *err = -EIO; |
554 | return NULL; | 555 | return NULL; |
555 | } | 556 | } |
556 | 557 | ||
557 | static int ufs_writepage(struct page *page, struct writeback_control *wbc) | 558 | static int ufs_writepage(struct page *page, struct writeback_control *wbc) |
558 | { | 559 | { |
559 | return block_write_full_page(page,ufs_getfrag_block,wbc); | 560 | return block_write_full_page(page,ufs_getfrag_block,wbc); |
560 | } | 561 | } |
561 | 562 | ||
562 | static int ufs_readpage(struct file *file, struct page *page) | 563 | static int ufs_readpage(struct file *file, struct page *page) |
563 | { | 564 | { |
564 | return block_read_full_page(page,ufs_getfrag_block); | 565 | return block_read_full_page(page,ufs_getfrag_block); |
565 | } | 566 | } |
566 | 567 | ||
567 | int __ufs_write_begin(struct file *file, struct address_space *mapping, | 568 | int __ufs_write_begin(struct file *file, struct address_space *mapping, |
568 | loff_t pos, unsigned len, unsigned flags, | 569 | loff_t pos, unsigned len, unsigned flags, |
569 | struct page **pagep, void **fsdata) | 570 | struct page **pagep, void **fsdata) |
570 | { | 571 | { |
571 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 572 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
572 | ufs_getfrag_block); | 573 | ufs_getfrag_block); |
573 | } | 574 | } |
574 | 575 | ||
575 | static int ufs_write_begin(struct file *file, struct address_space *mapping, | 576 | static int ufs_write_begin(struct file *file, struct address_space *mapping, |
576 | loff_t pos, unsigned len, unsigned flags, | 577 | loff_t pos, unsigned len, unsigned flags, |
577 | struct page **pagep, void **fsdata) | 578 | struct page **pagep, void **fsdata) |
578 | { | 579 | { |
579 | *pagep = NULL; | 580 | *pagep = NULL; |
580 | return __ufs_write_begin(file, mapping, pos, len, flags, pagep, fsdata); | 581 | return __ufs_write_begin(file, mapping, pos, len, flags, pagep, fsdata); |
581 | } | 582 | } |
582 | 583 | ||
583 | static sector_t ufs_bmap(struct address_space *mapping, sector_t block) | 584 | static sector_t ufs_bmap(struct address_space *mapping, sector_t block) |
584 | { | 585 | { |
585 | return generic_block_bmap(mapping,block,ufs_getfrag_block); | 586 | return generic_block_bmap(mapping,block,ufs_getfrag_block); |
586 | } | 587 | } |
587 | 588 | ||
588 | const struct address_space_operations ufs_aops = { | 589 | const struct address_space_operations ufs_aops = { |
589 | .readpage = ufs_readpage, | 590 | .readpage = ufs_readpage, |
590 | .writepage = ufs_writepage, | 591 | .writepage = ufs_writepage, |
591 | .sync_page = block_sync_page, | 592 | .sync_page = block_sync_page, |
592 | .write_begin = ufs_write_begin, | 593 | .write_begin = ufs_write_begin, |
593 | .write_end = generic_write_end, | 594 | .write_end = generic_write_end, |
594 | .bmap = ufs_bmap | 595 | .bmap = ufs_bmap |
595 | }; | 596 | }; |
596 | 597 | ||
597 | static void ufs_set_inode_ops(struct inode *inode) | 598 | static void ufs_set_inode_ops(struct inode *inode) |
598 | { | 599 | { |
599 | if (S_ISREG(inode->i_mode)) { | 600 | if (S_ISREG(inode->i_mode)) { |
600 | inode->i_op = &ufs_file_inode_operations; | 601 | inode->i_op = &ufs_file_inode_operations; |
601 | inode->i_fop = &ufs_file_operations; | 602 | inode->i_fop = &ufs_file_operations; |
602 | inode->i_mapping->a_ops = &ufs_aops; | 603 | inode->i_mapping->a_ops = &ufs_aops; |
603 | } else if (S_ISDIR(inode->i_mode)) { | 604 | } else if (S_ISDIR(inode->i_mode)) { |
604 | inode->i_op = &ufs_dir_inode_operations; | 605 | inode->i_op = &ufs_dir_inode_operations; |
605 | inode->i_fop = &ufs_dir_operations; | 606 | inode->i_fop = &ufs_dir_operations; |
606 | inode->i_mapping->a_ops = &ufs_aops; | 607 | inode->i_mapping->a_ops = &ufs_aops; |
607 | } else if (S_ISLNK(inode->i_mode)) { | 608 | } else if (S_ISLNK(inode->i_mode)) { |
608 | if (!inode->i_blocks) | 609 | if (!inode->i_blocks) |
609 | inode->i_op = &ufs_fast_symlink_inode_operations; | 610 | inode->i_op = &ufs_fast_symlink_inode_operations; |
610 | else { | 611 | else { |
611 | inode->i_op = &page_symlink_inode_operations; | 612 | inode->i_op = &page_symlink_inode_operations; |
612 | inode->i_mapping->a_ops = &ufs_aops; | 613 | inode->i_mapping->a_ops = &ufs_aops; |
613 | } | 614 | } |
614 | } else | 615 | } else |
615 | init_special_inode(inode, inode->i_mode, | 616 | init_special_inode(inode, inode->i_mode, |
616 | ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); | 617 | ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); |
617 | } | 618 | } |
618 | 619 | ||
619 | static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) | 620 | static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) |
620 | { | 621 | { |
621 | struct ufs_inode_info *ufsi = UFS_I(inode); | 622 | struct ufs_inode_info *ufsi = UFS_I(inode); |
622 | struct super_block *sb = inode->i_sb; | 623 | struct super_block *sb = inode->i_sb; |
623 | mode_t mode; | 624 | mode_t mode; |
624 | unsigned i; | 625 | unsigned i; |
625 | 626 | ||
626 | /* | 627 | /* |
627 | * Copy data to the in-core inode. | 628 | * Copy data to the in-core inode. |
628 | */ | 629 | */ |
629 | inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); | 630 | inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); |
630 | inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); | 631 | inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); |
631 | if (inode->i_nlink == 0) { | 632 | if (inode->i_nlink == 0) { |
632 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); | 633 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); |
633 | return -1; | 634 | return -1; |
634 | } | 635 | } |
635 | 636 | ||
636 | /* | 637 | /* |
637 | * Linux now has 32-bit uid and gid, so we can support EFT. | 638 | * Linux now has 32-bit uid and gid, so we can support EFT. |
638 | */ | 639 | */ |
639 | inode->i_uid = ufs_get_inode_uid(sb, ufs_inode); | 640 | inode->i_uid = ufs_get_inode_uid(sb, ufs_inode); |
640 | inode->i_gid = ufs_get_inode_gid(sb, ufs_inode); | 641 | inode->i_gid = ufs_get_inode_gid(sb, ufs_inode); |
641 | 642 | ||
642 | inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); | 643 | inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); |
643 | inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); | 644 | inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); |
644 | inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec); | 645 | inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec); |
645 | inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec); | 646 | inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec); |
646 | inode->i_mtime.tv_nsec = 0; | 647 | inode->i_mtime.tv_nsec = 0; |
647 | inode->i_atime.tv_nsec = 0; | 648 | inode->i_atime.tv_nsec = 0; |
648 | inode->i_ctime.tv_nsec = 0; | 649 | inode->i_ctime.tv_nsec = 0; |
649 | inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); | 650 | inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); |
650 | inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen); | 651 | inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen); |
651 | ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); | 652 | ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); |
652 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); | 653 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); |
653 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); | 654 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); |
654 | 655 | ||
655 | 656 | ||
656 | if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { | 657 | if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { |
657 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) | 658 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) |
658 | ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; | 659 | ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; |
659 | } else { | 660 | } else { |
660 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 661 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
661 | ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; | 662 | ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; |
662 | } | 663 | } |
663 | return 0; | 664 | return 0; |
664 | } | 665 | } |
665 | 666 | ||
666 | static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) | 667 | static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) |
667 | { | 668 | { |
668 | struct ufs_inode_info *ufsi = UFS_I(inode); | 669 | struct ufs_inode_info *ufsi = UFS_I(inode); |
669 | struct super_block *sb = inode->i_sb; | 670 | struct super_block *sb = inode->i_sb; |
670 | mode_t mode; | 671 | mode_t mode; |
671 | unsigned i; | 672 | unsigned i; |
672 | 673 | ||
673 | UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino); | 674 | UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino); |
674 | /* | 675 | /* |
675 | * Copy data to the in-core inode. | 676 | * Copy data to the in-core inode. |
676 | */ | 677 | */ |
677 | inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); | 678 | inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode); |
678 | inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); | 679 | inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink); |
679 | if (inode->i_nlink == 0) { | 680 | if (inode->i_nlink == 0) { |
680 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); | 681 | ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); |
681 | return -1; | 682 | return -1; |
682 | } | 683 | } |
683 | 684 | ||
684 | /* | 685 | /* |
685 | * Linux now has 32-bit uid and gid, so we can support EFT. | 686 | * Linux now has 32-bit uid and gid, so we can support EFT. |
686 | */ | 687 | */ |
687 | inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid); | 688 | inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid); |
688 | inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); | 689 | inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); |
689 | 690 | ||
690 | inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); | 691 | inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); |
691 | inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime); | 692 | inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime); |
692 | inode->i_ctime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_ctime); | 693 | inode->i_ctime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_ctime); |
693 | inode->i_mtime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_mtime); | 694 | inode->i_mtime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_mtime); |
694 | inode->i_atime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_atimensec); | 695 | inode->i_atime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_atimensec); |
695 | inode->i_ctime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_ctimensec); | 696 | inode->i_ctime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_ctimensec); |
696 | inode->i_mtime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_mtimensec); | 697 | inode->i_mtime.tv_nsec = fs32_to_cpu(sb, ufs2_inode->ui_mtimensec); |
697 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); | 698 | inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); |
698 | inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); | 699 | inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen); |
699 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); | 700 | ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); |
700 | /* | 701 | /* |
701 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); | 702 | ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); |
702 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); | 703 | ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); |
703 | */ | 704 | */ |
704 | 705 | ||
705 | if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { | 706 | if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { |
706 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) | 707 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) |
707 | ufsi->i_u1.u2_i_data[i] = | 708 | ufsi->i_u1.u2_i_data[i] = |
708 | ufs2_inode->ui_u2.ui_addr.ui_db[i]; | 709 | ufs2_inode->ui_u2.ui_addr.ui_db[i]; |
709 | } else { | 710 | } else { |
710 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 711 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
711 | ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; | 712 | ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; |
712 | } | 713 | } |
713 | return 0; | 714 | return 0; |
714 | } | 715 | } |
715 | 716 | ||
716 | void ufs_read_inode(struct inode * inode) | 717 | void ufs_read_inode(struct inode * inode) |
717 | { | 718 | { |
718 | struct ufs_inode_info *ufsi = UFS_I(inode); | 719 | struct ufs_inode_info *ufsi = UFS_I(inode); |
719 | struct super_block * sb; | 720 | struct super_block * sb; |
720 | struct ufs_sb_private_info * uspi; | 721 | struct ufs_sb_private_info * uspi; |
721 | struct buffer_head * bh; | 722 | struct buffer_head * bh; |
722 | int err; | 723 | int err; |
723 | 724 | ||
724 | UFSD("ENTER, ino %lu\n", inode->i_ino); | 725 | UFSD("ENTER, ino %lu\n", inode->i_ino); |
725 | 726 | ||
726 | sb = inode->i_sb; | 727 | sb = inode->i_sb; |
727 | uspi = UFS_SB(sb)->s_uspi; | 728 | uspi = UFS_SB(sb)->s_uspi; |
728 | 729 | ||
729 | if (inode->i_ino < UFS_ROOTINO || | 730 | if (inode->i_ino < UFS_ROOTINO || |
730 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { | 731 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { |
731 | ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n", | 732 | ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n", |
732 | inode->i_ino); | 733 | inode->i_ino); |
733 | goto bad_inode; | 734 | goto bad_inode; |
734 | } | 735 | } |
735 | 736 | ||
736 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); | 737 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); |
737 | if (!bh) { | 738 | if (!bh) { |
738 | ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n", | 739 | ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n", |
739 | inode->i_ino); | 740 | inode->i_ino); |
740 | goto bad_inode; | 741 | goto bad_inode; |
741 | } | 742 | } |
742 | if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 743 | if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { |
743 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; | 744 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; |
744 | 745 | ||
745 | err = ufs2_read_inode(inode, | 746 | err = ufs2_read_inode(inode, |
746 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); | 747 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); |
747 | } else { | 748 | } else { |
748 | struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; | 749 | struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; |
749 | 750 | ||
750 | err = ufs1_read_inode(inode, | 751 | err = ufs1_read_inode(inode, |
751 | ufs_inode + ufs_inotofsbo(inode->i_ino)); | 752 | ufs_inode + ufs_inotofsbo(inode->i_ino)); |
752 | } | 753 | } |
753 | 754 | ||
754 | if (err) | 755 | if (err) |
755 | goto bad_inode; | 756 | goto bad_inode; |
756 | inode->i_version++; | 757 | inode->i_version++; |
757 | ufsi->i_lastfrag = | 758 | ufsi->i_lastfrag = |
758 | (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; | 759 | (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; |
759 | ufsi->i_dir_start_lookup = 0; | 760 | ufsi->i_dir_start_lookup = 0; |
760 | ufsi->i_osync = 0; | 761 | ufsi->i_osync = 0; |
761 | 762 | ||
762 | ufs_set_inode_ops(inode); | 763 | ufs_set_inode_ops(inode); |
763 | 764 | ||
764 | brelse(bh); | 765 | brelse(bh); |
765 | 766 | ||
766 | UFSD("EXIT\n"); | 767 | UFSD("EXIT\n"); |
767 | return; | 768 | return; |
768 | 769 | ||
769 | bad_inode: | 770 | bad_inode: |
770 | make_bad_inode(inode); | 771 | make_bad_inode(inode); |
771 | } | 772 | } |
772 | 773 | ||
773 | static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) | 774 | static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) |
774 | { | 775 | { |
775 | struct super_block *sb = inode->i_sb; | 776 | struct super_block *sb = inode->i_sb; |
776 | struct ufs_inode_info *ufsi = UFS_I(inode); | 777 | struct ufs_inode_info *ufsi = UFS_I(inode); |
777 | unsigned i; | 778 | unsigned i; |
778 | 779 | ||
779 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); | 780 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); |
780 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); | 781 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); |
781 | 782 | ||
782 | ufs_set_inode_uid(sb, ufs_inode, inode->i_uid); | 783 | ufs_set_inode_uid(sb, ufs_inode, inode->i_uid); |
783 | ufs_set_inode_gid(sb, ufs_inode, inode->i_gid); | 784 | ufs_set_inode_gid(sb, ufs_inode, inode->i_gid); |
784 | 785 | ||
785 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); | 786 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); |
786 | ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); | 787 | ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); |
787 | ufs_inode->ui_atime.tv_usec = 0; | 788 | ufs_inode->ui_atime.tv_usec = 0; |
788 | ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); | 789 | ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec); |
789 | ufs_inode->ui_ctime.tv_usec = 0; | 790 | ufs_inode->ui_ctime.tv_usec = 0; |
790 | ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); | 791 | ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec); |
791 | ufs_inode->ui_mtime.tv_usec = 0; | 792 | ufs_inode->ui_mtime.tv_usec = 0; |
792 | ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); | 793 | ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks); |
793 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); | 794 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); |
794 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); | 795 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); |
795 | 796 | ||
796 | if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) { | 797 | if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) { |
797 | ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); | 798 | ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow); |
798 | ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); | 799 | ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); |
799 | } | 800 | } |
800 | 801 | ||
801 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | 802 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { |
802 | /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ | 803 | /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ |
803 | ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; | 804 | ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; |
804 | } else if (inode->i_blocks) { | 805 | } else if (inode->i_blocks) { |
805 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) | 806 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) |
806 | ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; | 807 | ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; |
807 | } | 808 | } |
808 | else { | 809 | else { |
809 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 810 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
810 | ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; | 811 | ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; |
811 | } | 812 | } |
812 | 813 | ||
813 | if (!inode->i_nlink) | 814 | if (!inode->i_nlink) |
814 | memset (ufs_inode, 0, sizeof(struct ufs_inode)); | 815 | memset (ufs_inode, 0, sizeof(struct ufs_inode)); |
815 | } | 816 | } |
816 | 817 | ||
817 | static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) | 818 | static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) |
818 | { | 819 | { |
819 | struct super_block *sb = inode->i_sb; | 820 | struct super_block *sb = inode->i_sb; |
820 | struct ufs_inode_info *ufsi = UFS_I(inode); | 821 | struct ufs_inode_info *ufsi = UFS_I(inode); |
821 | unsigned i; | 822 | unsigned i; |
822 | 823 | ||
823 | UFSD("ENTER\n"); | 824 | UFSD("ENTER\n"); |
824 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); | 825 | ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); |
825 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); | 826 | ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); |
826 | 827 | ||
827 | ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid); | 828 | ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid); |
828 | ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); | 829 | ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); |
829 | 830 | ||
830 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); | 831 | ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); |
831 | ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec); | 832 | ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec); |
832 | ufs_inode->ui_atimensec = cpu_to_fs32(sb, inode->i_atime.tv_nsec); | 833 | ufs_inode->ui_atimensec = cpu_to_fs32(sb, inode->i_atime.tv_nsec); |
833 | ufs_inode->ui_ctime = cpu_to_fs64(sb, inode->i_ctime.tv_sec); | 834 | ufs_inode->ui_ctime = cpu_to_fs64(sb, inode->i_ctime.tv_sec); |
834 | ufs_inode->ui_ctimensec = cpu_to_fs32(sb, inode->i_ctime.tv_nsec); | 835 | ufs_inode->ui_ctimensec = cpu_to_fs32(sb, inode->i_ctime.tv_nsec); |
835 | ufs_inode->ui_mtime = cpu_to_fs64(sb, inode->i_mtime.tv_sec); | 836 | ufs_inode->ui_mtime = cpu_to_fs64(sb, inode->i_mtime.tv_sec); |
836 | ufs_inode->ui_mtimensec = cpu_to_fs32(sb, inode->i_mtime.tv_nsec); | 837 | ufs_inode->ui_mtimensec = cpu_to_fs32(sb, inode->i_mtime.tv_nsec); |
837 | 838 | ||
838 | ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); | 839 | ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks); |
839 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); | 840 | ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags); |
840 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); | 841 | ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation); |
841 | 842 | ||
842 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | 843 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { |
843 | /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ | 844 | /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ |
844 | ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0]; | 845 | ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0]; |
845 | } else if (inode->i_blocks) { | 846 | } else if (inode->i_blocks) { |
846 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) | 847 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) |
847 | ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i]; | 848 | ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i]; |
848 | } else { | 849 | } else { |
849 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) | 850 | for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) |
850 | ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; | 851 | ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i]; |
851 | } | 852 | } |
852 | 853 | ||
853 | if (!inode->i_nlink) | 854 | if (!inode->i_nlink) |
854 | memset (ufs_inode, 0, sizeof(struct ufs2_inode)); | 855 | memset (ufs_inode, 0, sizeof(struct ufs2_inode)); |
855 | UFSD("EXIT\n"); | 856 | UFSD("EXIT\n"); |
856 | } | 857 | } |
857 | 858 | ||
858 | static int ufs_update_inode(struct inode * inode, int do_sync) | 859 | static int ufs_update_inode(struct inode * inode, int do_sync) |
859 | { | 860 | { |
860 | struct super_block *sb = inode->i_sb; | 861 | struct super_block *sb = inode->i_sb; |
861 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 862 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
862 | struct buffer_head * bh; | 863 | struct buffer_head * bh; |
863 | 864 | ||
864 | UFSD("ENTER, ino %lu\n", inode->i_ino); | 865 | UFSD("ENTER, ino %lu\n", inode->i_ino); |
865 | 866 | ||
866 | if (inode->i_ino < UFS_ROOTINO || | 867 | if (inode->i_ino < UFS_ROOTINO || |
867 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { | 868 | inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { |
868 | ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); | 869 | ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); |
869 | return -1; | 870 | return -1; |
870 | } | 871 | } |
871 | 872 | ||
872 | bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); | 873 | bh = sb_bread(sb, ufs_inotofsba(inode->i_ino)); |
873 | if (!bh) { | 874 | if (!bh) { |
874 | ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); | 875 | ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); |
875 | return -1; | 876 | return -1; |
876 | } | 877 | } |
877 | if (uspi->fs_magic == UFS2_MAGIC) { | 878 | if (uspi->fs_magic == UFS2_MAGIC) { |
878 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; | 879 | struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; |
879 | 880 | ||
880 | ufs2_update_inode(inode, | 881 | ufs2_update_inode(inode, |
881 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); | 882 | ufs2_inode + ufs_inotofsbo(inode->i_ino)); |
882 | } else { | 883 | } else { |
883 | struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data; | 884 | struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data; |
884 | 885 | ||
885 | ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); | 886 | ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); |
886 | } | 887 | } |
887 | 888 | ||
888 | mark_buffer_dirty(bh); | 889 | mark_buffer_dirty(bh); |
889 | if (do_sync) | 890 | if (do_sync) |
890 | sync_dirty_buffer(bh); | 891 | sync_dirty_buffer(bh); |
891 | brelse (bh); | 892 | brelse (bh); |
892 | 893 | ||
893 | UFSD("EXIT\n"); | 894 | UFSD("EXIT\n"); |
894 | return 0; | 895 | return 0; |
895 | } | 896 | } |
896 | 897 | ||
897 | int ufs_write_inode (struct inode * inode, int wait) | 898 | int ufs_write_inode (struct inode * inode, int wait) |
898 | { | 899 | { |
899 | int ret; | 900 | int ret; |
900 | lock_kernel(); | 901 | lock_kernel(); |
901 | ret = ufs_update_inode (inode, wait); | 902 | ret = ufs_update_inode (inode, wait); |
902 | unlock_kernel(); | 903 | unlock_kernel(); |
903 | return ret; | 904 | return ret; |
904 | } | 905 | } |
905 | 906 | ||
906 | int ufs_sync_inode (struct inode *inode) | 907 | int ufs_sync_inode (struct inode *inode) |
907 | { | 908 | { |
908 | return ufs_update_inode (inode, 1); | 909 | return ufs_update_inode (inode, 1); |
909 | } | 910 | } |
910 | 911 | ||
911 | void ufs_delete_inode (struct inode * inode) | 912 | void ufs_delete_inode (struct inode * inode) |
912 | { | 913 | { |
913 | loff_t old_i_size; | 914 | loff_t old_i_size; |
914 | 915 | ||
915 | truncate_inode_pages(&inode->i_data, 0); | 916 | truncate_inode_pages(&inode->i_data, 0); |
916 | if (is_bad_inode(inode)) | 917 | if (is_bad_inode(inode)) |
917 | goto no_delete; | 918 | goto no_delete; |
918 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ | 919 | /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ |
919 | lock_kernel(); | 920 | lock_kernel(); |
920 | mark_inode_dirty(inode); | 921 | mark_inode_dirty(inode); |
921 | ufs_update_inode(inode, IS_SYNC(inode)); | 922 | ufs_update_inode(inode, IS_SYNC(inode)); |
922 | old_i_size = inode->i_size; | 923 | old_i_size = inode->i_size; |
923 | inode->i_size = 0; | 924 | inode->i_size = 0; |
924 | if (inode->i_blocks && ufs_truncate(inode, old_i_size)) | 925 | if (inode->i_blocks && ufs_truncate(inode, old_i_size)) |
925 | ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); | 926 | ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); |
926 | ufs_free_inode (inode); | 927 | ufs_free_inode (inode); |
927 | unlock_kernel(); | 928 | unlock_kernel(); |
928 | return; | 929 | return; |
929 | no_delete: | 930 | no_delete: |
930 | clear_inode(inode); /* We must guarantee clearing of inode... */ | 931 | clear_inode(inode); /* We must guarantee clearing of inode... */ |
931 | } | 932 | } |
932 | 933 |
fs/ufs/namei.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/namei.c | 2 | * linux/fs/ufs/namei.c |
3 | * | 3 | * |
4 | * Migration to usage of "page cache" on May 2006 by | 4 | * Migration to usage of "page cache" on May 2006 by |
5 | * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base. | 5 | * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base. |
6 | * | 6 | * |
7 | * Copyright (C) 1998 | 7 | * Copyright (C) 1998 |
8 | * Daniel Pirkl <daniel.pirkl@email.cz> | 8 | * Daniel Pirkl <daniel.pirkl@email.cz> |
9 | * Charles University, Faculty of Mathematics and Physics | 9 | * Charles University, Faculty of Mathematics and Physics |
10 | * | 10 | * |
11 | * from | 11 | * from |
12 | * | 12 | * |
13 | * linux/fs/ext2/namei.c | 13 | * linux/fs/ext2/namei.c |
14 | * | 14 | * |
15 | * Copyright (C) 1992, 1993, 1994, 1995 | 15 | * Copyright (C) 1992, 1993, 1994, 1995 |
16 | * Remy Card (card@masi.ibp.fr) | 16 | * Remy Card (card@masi.ibp.fr) |
17 | * Laboratoire MASI - Institut Blaise Pascal | 17 | * Laboratoire MASI - Institut Blaise Pascal |
18 | * Universite Pierre et Marie Curie (Paris VI) | 18 | * Universite Pierre et Marie Curie (Paris VI) |
19 | * | 19 | * |
20 | * from | 20 | * from |
21 | * | 21 | * |
22 | * linux/fs/minix/namei.c | 22 | * linux/fs/minix/namei.c |
23 | * | 23 | * |
24 | * Copyright (C) 1991, 1992 Linus Torvalds | 24 | * Copyright (C) 1991, 1992 Linus Torvalds |
25 | * | 25 | * |
26 | * Big-endian to little-endian byte-swapping/bitmaps by | 26 | * Big-endian to little-endian byte-swapping/bitmaps by |
27 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 27 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/time.h> | 30 | #include <linux/time.h> |
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/ufs_fs.h> | 32 | #include <linux/ufs_fs.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include "swab.h" /* will go away - see comment in mknod() */ | 34 | #include "ufs.h" |
35 | #include "util.h" | 35 | #include "util.h" |
36 | 36 | ||
37 | static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) | 37 | static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) |
38 | { | 38 | { |
39 | int err = ufs_add_link(dentry, inode); | 39 | int err = ufs_add_link(dentry, inode); |
40 | if (!err) { | 40 | if (!err) { |
41 | d_instantiate(dentry, inode); | 41 | d_instantiate(dentry, inode); |
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | inode_dec_link_count(inode); | 44 | inode_dec_link_count(inode); |
45 | iput(inode); | 45 | iput(inode); |
46 | return err; | 46 | return err; |
47 | } | 47 | } |
48 | 48 | ||
49 | static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 49 | static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) |
50 | { | 50 | { |
51 | struct inode * inode = NULL; | 51 | struct inode * inode = NULL; |
52 | ino_t ino; | 52 | ino_t ino; |
53 | 53 | ||
54 | if (dentry->d_name.len > UFS_MAXNAMLEN) | 54 | if (dentry->d_name.len > UFS_MAXNAMLEN) |
55 | return ERR_PTR(-ENAMETOOLONG); | 55 | return ERR_PTR(-ENAMETOOLONG); |
56 | 56 | ||
57 | lock_kernel(); | 57 | lock_kernel(); |
58 | ino = ufs_inode_by_name(dir, dentry); | 58 | ino = ufs_inode_by_name(dir, dentry); |
59 | if (ino) { | 59 | if (ino) { |
60 | inode = iget(dir->i_sb, ino); | 60 | inode = iget(dir->i_sb, ino); |
61 | if (!inode) { | 61 | if (!inode) { |
62 | unlock_kernel(); | 62 | unlock_kernel(); |
63 | return ERR_PTR(-EACCES); | 63 | return ERR_PTR(-EACCES); |
64 | } | 64 | } |
65 | } | 65 | } |
66 | unlock_kernel(); | 66 | unlock_kernel(); |
67 | d_add(dentry, inode); | 67 | d_add(dentry, inode); |
68 | return NULL; | 68 | return NULL; |
69 | } | 69 | } |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * By the time this is called, we already have created | 72 | * By the time this is called, we already have created |
73 | * the directory cache entry for the new file, but it | 73 | * the directory cache entry for the new file, but it |
74 | * is so far negative - it has no inode. | 74 | * is so far negative - it has no inode. |
75 | * | 75 | * |
76 | * If the create succeeds, we fill in the inode information | 76 | * If the create succeeds, we fill in the inode information |
77 | * with d_instantiate(). | 77 | * with d_instantiate(). |
78 | */ | 78 | */ |
79 | static int ufs_create (struct inode * dir, struct dentry * dentry, int mode, | 79 | static int ufs_create (struct inode * dir, struct dentry * dentry, int mode, |
80 | struct nameidata *nd) | 80 | struct nameidata *nd) |
81 | { | 81 | { |
82 | struct inode *inode; | 82 | struct inode *inode; |
83 | int err; | 83 | int err; |
84 | 84 | ||
85 | UFSD("BEGIN\n"); | 85 | UFSD("BEGIN\n"); |
86 | inode = ufs_new_inode(dir, mode); | 86 | inode = ufs_new_inode(dir, mode); |
87 | err = PTR_ERR(inode); | 87 | err = PTR_ERR(inode); |
88 | 88 | ||
89 | if (!IS_ERR(inode)) { | 89 | if (!IS_ERR(inode)) { |
90 | inode->i_op = &ufs_file_inode_operations; | 90 | inode->i_op = &ufs_file_inode_operations; |
91 | inode->i_fop = &ufs_file_operations; | 91 | inode->i_fop = &ufs_file_operations; |
92 | inode->i_mapping->a_ops = &ufs_aops; | 92 | inode->i_mapping->a_ops = &ufs_aops; |
93 | mark_inode_dirty(inode); | 93 | mark_inode_dirty(inode); |
94 | lock_kernel(); | 94 | lock_kernel(); |
95 | err = ufs_add_nondir(dentry, inode); | 95 | err = ufs_add_nondir(dentry, inode); |
96 | unlock_kernel(); | 96 | unlock_kernel(); |
97 | } | 97 | } |
98 | UFSD("END: err=%d\n", err); | 98 | UFSD("END: err=%d\n", err); |
99 | return err; | 99 | return err; |
100 | } | 100 | } |
101 | 101 | ||
102 | static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) | 102 | static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) |
103 | { | 103 | { |
104 | struct inode *inode; | 104 | struct inode *inode; |
105 | int err; | 105 | int err; |
106 | 106 | ||
107 | if (!old_valid_dev(rdev)) | 107 | if (!old_valid_dev(rdev)) |
108 | return -EINVAL; | 108 | return -EINVAL; |
109 | inode = ufs_new_inode(dir, mode); | 109 | inode = ufs_new_inode(dir, mode); |
110 | err = PTR_ERR(inode); | 110 | err = PTR_ERR(inode); |
111 | if (!IS_ERR(inode)) { | 111 | if (!IS_ERR(inode)) { |
112 | init_special_inode(inode, mode, rdev); | 112 | init_special_inode(inode, mode, rdev); |
113 | /* NOTE: that'll go when we get wide dev_t */ | ||
114 | ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev); | 113 | ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev); |
115 | mark_inode_dirty(inode); | 114 | mark_inode_dirty(inode); |
116 | lock_kernel(); | 115 | lock_kernel(); |
117 | err = ufs_add_nondir(dentry, inode); | 116 | err = ufs_add_nondir(dentry, inode); |
118 | unlock_kernel(); | 117 | unlock_kernel(); |
119 | } | 118 | } |
120 | return err; | 119 | return err; |
121 | } | 120 | } |
122 | 121 | ||
123 | static int ufs_symlink (struct inode * dir, struct dentry * dentry, | 122 | static int ufs_symlink (struct inode * dir, struct dentry * dentry, |
124 | const char * symname) | 123 | const char * symname) |
125 | { | 124 | { |
126 | struct super_block * sb = dir->i_sb; | 125 | struct super_block * sb = dir->i_sb; |
127 | int err = -ENAMETOOLONG; | 126 | int err = -ENAMETOOLONG; |
128 | unsigned l = strlen(symname)+1; | 127 | unsigned l = strlen(symname)+1; |
129 | struct inode * inode; | 128 | struct inode * inode; |
130 | 129 | ||
131 | if (l > sb->s_blocksize) | 130 | if (l > sb->s_blocksize) |
132 | goto out_notlocked; | 131 | goto out_notlocked; |
133 | 132 | ||
134 | lock_kernel(); | 133 | lock_kernel(); |
135 | inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); | 134 | inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); |
136 | err = PTR_ERR(inode); | 135 | err = PTR_ERR(inode); |
137 | if (IS_ERR(inode)) | 136 | if (IS_ERR(inode)) |
138 | goto out; | 137 | goto out; |
139 | 138 | ||
140 | if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) { | 139 | if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) { |
141 | /* slow symlink */ | 140 | /* slow symlink */ |
142 | inode->i_op = &page_symlink_inode_operations; | 141 | inode->i_op = &page_symlink_inode_operations; |
143 | inode->i_mapping->a_ops = &ufs_aops; | 142 | inode->i_mapping->a_ops = &ufs_aops; |
144 | err = page_symlink(inode, symname, l); | 143 | err = page_symlink(inode, symname, l); |
145 | if (err) | 144 | if (err) |
146 | goto out_fail; | 145 | goto out_fail; |
147 | } else { | 146 | } else { |
148 | /* fast symlink */ | 147 | /* fast symlink */ |
149 | inode->i_op = &ufs_fast_symlink_inode_operations; | 148 | inode->i_op = &ufs_fast_symlink_inode_operations; |
150 | memcpy((char*)&UFS_I(inode)->i_u1.i_data,symname,l); | 149 | memcpy((char*)&UFS_I(inode)->i_u1.i_data,symname,l); |
151 | inode->i_size = l-1; | 150 | inode->i_size = l-1; |
152 | } | 151 | } |
153 | mark_inode_dirty(inode); | 152 | mark_inode_dirty(inode); |
154 | 153 | ||
155 | err = ufs_add_nondir(dentry, inode); | 154 | err = ufs_add_nondir(dentry, inode); |
156 | out: | 155 | out: |
157 | unlock_kernel(); | 156 | unlock_kernel(); |
158 | out_notlocked: | 157 | out_notlocked: |
159 | return err; | 158 | return err; |
160 | 159 | ||
161 | out_fail: | 160 | out_fail: |
162 | inode_dec_link_count(inode); | 161 | inode_dec_link_count(inode); |
163 | iput(inode); | 162 | iput(inode); |
164 | goto out; | 163 | goto out; |
165 | } | 164 | } |
166 | 165 | ||
167 | static int ufs_link (struct dentry * old_dentry, struct inode * dir, | 166 | static int ufs_link (struct dentry * old_dentry, struct inode * dir, |
168 | struct dentry *dentry) | 167 | struct dentry *dentry) |
169 | { | 168 | { |
170 | struct inode *inode = old_dentry->d_inode; | 169 | struct inode *inode = old_dentry->d_inode; |
171 | int error; | 170 | int error; |
172 | 171 | ||
173 | lock_kernel(); | 172 | lock_kernel(); |
174 | if (inode->i_nlink >= UFS_LINK_MAX) { | 173 | if (inode->i_nlink >= UFS_LINK_MAX) { |
175 | unlock_kernel(); | 174 | unlock_kernel(); |
176 | return -EMLINK; | 175 | return -EMLINK; |
177 | } | 176 | } |
178 | 177 | ||
179 | inode->i_ctime = CURRENT_TIME_SEC; | 178 | inode->i_ctime = CURRENT_TIME_SEC; |
180 | inode_inc_link_count(inode); | 179 | inode_inc_link_count(inode); |
181 | atomic_inc(&inode->i_count); | 180 | atomic_inc(&inode->i_count); |
182 | 181 | ||
183 | error = ufs_add_nondir(dentry, inode); | 182 | error = ufs_add_nondir(dentry, inode); |
184 | unlock_kernel(); | 183 | unlock_kernel(); |
185 | return error; | 184 | return error; |
186 | } | 185 | } |
187 | 186 | ||
188 | static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) | 187 | static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode) |
189 | { | 188 | { |
190 | struct inode * inode; | 189 | struct inode * inode; |
191 | int err = -EMLINK; | 190 | int err = -EMLINK; |
192 | 191 | ||
193 | if (dir->i_nlink >= UFS_LINK_MAX) | 192 | if (dir->i_nlink >= UFS_LINK_MAX) |
194 | goto out; | 193 | goto out; |
195 | 194 | ||
196 | lock_kernel(); | 195 | lock_kernel(); |
197 | inode_inc_link_count(dir); | 196 | inode_inc_link_count(dir); |
198 | 197 | ||
199 | inode = ufs_new_inode(dir, S_IFDIR|mode); | 198 | inode = ufs_new_inode(dir, S_IFDIR|mode); |
200 | err = PTR_ERR(inode); | 199 | err = PTR_ERR(inode); |
201 | if (IS_ERR(inode)) | 200 | if (IS_ERR(inode)) |
202 | goto out_dir; | 201 | goto out_dir; |
203 | 202 | ||
204 | inode->i_op = &ufs_dir_inode_operations; | 203 | inode->i_op = &ufs_dir_inode_operations; |
205 | inode->i_fop = &ufs_dir_operations; | 204 | inode->i_fop = &ufs_dir_operations; |
206 | inode->i_mapping->a_ops = &ufs_aops; | 205 | inode->i_mapping->a_ops = &ufs_aops; |
207 | 206 | ||
208 | inode_inc_link_count(inode); | 207 | inode_inc_link_count(inode); |
209 | 208 | ||
210 | err = ufs_make_empty(inode, dir); | 209 | err = ufs_make_empty(inode, dir); |
211 | if (err) | 210 | if (err) |
212 | goto out_fail; | 211 | goto out_fail; |
213 | 212 | ||
214 | err = ufs_add_link(dentry, inode); | 213 | err = ufs_add_link(dentry, inode); |
215 | if (err) | 214 | if (err) |
216 | goto out_fail; | 215 | goto out_fail; |
217 | unlock_kernel(); | 216 | unlock_kernel(); |
218 | 217 | ||
219 | d_instantiate(dentry, inode); | 218 | d_instantiate(dentry, inode); |
220 | out: | 219 | out: |
221 | return err; | 220 | return err; |
222 | 221 | ||
223 | out_fail: | 222 | out_fail: |
224 | inode_dec_link_count(inode); | 223 | inode_dec_link_count(inode); |
225 | inode_dec_link_count(inode); | 224 | inode_dec_link_count(inode); |
226 | iput (inode); | 225 | iput (inode); |
227 | out_dir: | 226 | out_dir: |
228 | inode_dec_link_count(dir); | 227 | inode_dec_link_count(dir); |
229 | unlock_kernel(); | 228 | unlock_kernel(); |
230 | goto out; | 229 | goto out; |
231 | } | 230 | } |
232 | 231 | ||
233 | static int ufs_unlink(struct inode *dir, struct dentry *dentry) | 232 | static int ufs_unlink(struct inode *dir, struct dentry *dentry) |
234 | { | 233 | { |
235 | struct inode * inode = dentry->d_inode; | 234 | struct inode * inode = dentry->d_inode; |
236 | struct ufs_dir_entry *de; | 235 | struct ufs_dir_entry *de; |
237 | struct page *page; | 236 | struct page *page; |
238 | int err = -ENOENT; | 237 | int err = -ENOENT; |
239 | 238 | ||
240 | de = ufs_find_entry(dir, dentry, &page); | 239 | de = ufs_find_entry(dir, dentry, &page); |
241 | if (!de) | 240 | if (!de) |
242 | goto out; | 241 | goto out; |
243 | 242 | ||
244 | err = ufs_delete_entry(dir, de, page); | 243 | err = ufs_delete_entry(dir, de, page); |
245 | if (err) | 244 | if (err) |
246 | goto out; | 245 | goto out; |
247 | 246 | ||
248 | inode->i_ctime = dir->i_ctime; | 247 | inode->i_ctime = dir->i_ctime; |
249 | inode_dec_link_count(inode); | 248 | inode_dec_link_count(inode); |
250 | err = 0; | 249 | err = 0; |
251 | out: | 250 | out: |
252 | return err; | 251 | return err; |
253 | } | 252 | } |
254 | 253 | ||
255 | static int ufs_rmdir (struct inode * dir, struct dentry *dentry) | 254 | static int ufs_rmdir (struct inode * dir, struct dentry *dentry) |
256 | { | 255 | { |
257 | struct inode * inode = dentry->d_inode; | 256 | struct inode * inode = dentry->d_inode; |
258 | int err= -ENOTEMPTY; | 257 | int err= -ENOTEMPTY; |
259 | 258 | ||
260 | lock_kernel(); | 259 | lock_kernel(); |
261 | if (ufs_empty_dir (inode)) { | 260 | if (ufs_empty_dir (inode)) { |
262 | err = ufs_unlink(dir, dentry); | 261 | err = ufs_unlink(dir, dentry); |
263 | if (!err) { | 262 | if (!err) { |
264 | inode->i_size = 0; | 263 | inode->i_size = 0; |
265 | inode_dec_link_count(inode); | 264 | inode_dec_link_count(inode); |
266 | inode_dec_link_count(dir); | 265 | inode_dec_link_count(dir); |
267 | } | 266 | } |
268 | } | 267 | } |
269 | unlock_kernel(); | 268 | unlock_kernel(); |
270 | return err; | 269 | return err; |
271 | } | 270 | } |
272 | 271 | ||
273 | static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, | 272 | static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, |
274 | struct inode *new_dir, struct dentry *new_dentry) | 273 | struct inode *new_dir, struct dentry *new_dentry) |
275 | { | 274 | { |
276 | struct inode *old_inode = old_dentry->d_inode; | 275 | struct inode *old_inode = old_dentry->d_inode; |
277 | struct inode *new_inode = new_dentry->d_inode; | 276 | struct inode *new_inode = new_dentry->d_inode; |
278 | struct page *dir_page = NULL; | 277 | struct page *dir_page = NULL; |
279 | struct ufs_dir_entry * dir_de = NULL; | 278 | struct ufs_dir_entry * dir_de = NULL; |
280 | struct page *old_page; | 279 | struct page *old_page; |
281 | struct ufs_dir_entry *old_de; | 280 | struct ufs_dir_entry *old_de; |
282 | int err = -ENOENT; | 281 | int err = -ENOENT; |
283 | 282 | ||
284 | old_de = ufs_find_entry(old_dir, old_dentry, &old_page); | 283 | old_de = ufs_find_entry(old_dir, old_dentry, &old_page); |
285 | if (!old_de) | 284 | if (!old_de) |
286 | goto out; | 285 | goto out; |
287 | 286 | ||
288 | if (S_ISDIR(old_inode->i_mode)) { | 287 | if (S_ISDIR(old_inode->i_mode)) { |
289 | err = -EIO; | 288 | err = -EIO; |
290 | dir_de = ufs_dotdot(old_inode, &dir_page); | 289 | dir_de = ufs_dotdot(old_inode, &dir_page); |
291 | if (!dir_de) | 290 | if (!dir_de) |
292 | goto out_old; | 291 | goto out_old; |
293 | } | 292 | } |
294 | 293 | ||
295 | if (new_inode) { | 294 | if (new_inode) { |
296 | struct page *new_page; | 295 | struct page *new_page; |
297 | struct ufs_dir_entry *new_de; | 296 | struct ufs_dir_entry *new_de; |
298 | 297 | ||
299 | err = -ENOTEMPTY; | 298 | err = -ENOTEMPTY; |
300 | if (dir_de && !ufs_empty_dir(new_inode)) | 299 | if (dir_de && !ufs_empty_dir(new_inode)) |
301 | goto out_dir; | 300 | goto out_dir; |
302 | 301 | ||
303 | err = -ENOENT; | 302 | err = -ENOENT; |
304 | new_de = ufs_find_entry(new_dir, new_dentry, &new_page); | 303 | new_de = ufs_find_entry(new_dir, new_dentry, &new_page); |
305 | if (!new_de) | 304 | if (!new_de) |
306 | goto out_dir; | 305 | goto out_dir; |
307 | inode_inc_link_count(old_inode); | 306 | inode_inc_link_count(old_inode); |
308 | ufs_set_link(new_dir, new_de, new_page, old_inode); | 307 | ufs_set_link(new_dir, new_de, new_page, old_inode); |
309 | new_inode->i_ctime = CURRENT_TIME_SEC; | 308 | new_inode->i_ctime = CURRENT_TIME_SEC; |
310 | if (dir_de) | 309 | if (dir_de) |
311 | drop_nlink(new_inode); | 310 | drop_nlink(new_inode); |
312 | inode_dec_link_count(new_inode); | 311 | inode_dec_link_count(new_inode); |
313 | } else { | 312 | } else { |
314 | if (dir_de) { | 313 | if (dir_de) { |
315 | err = -EMLINK; | 314 | err = -EMLINK; |
316 | if (new_dir->i_nlink >= UFS_LINK_MAX) | 315 | if (new_dir->i_nlink >= UFS_LINK_MAX) |
317 | goto out_dir; | 316 | goto out_dir; |
318 | } | 317 | } |
319 | inode_inc_link_count(old_inode); | 318 | inode_inc_link_count(old_inode); |
320 | err = ufs_add_link(new_dentry, old_inode); | 319 | err = ufs_add_link(new_dentry, old_inode); |
321 | if (err) { | 320 | if (err) { |
322 | inode_dec_link_count(old_inode); | 321 | inode_dec_link_count(old_inode); |
323 | goto out_dir; | 322 | goto out_dir; |
324 | } | 323 | } |
325 | if (dir_de) | 324 | if (dir_de) |
326 | inode_inc_link_count(new_dir); | 325 | inode_inc_link_count(new_dir); |
327 | } | 326 | } |
328 | 327 | ||
329 | /* | 328 | /* |
330 | * Like most other Unix systems, set the ctime for inodes on a | 329 | * Like most other Unix systems, set the ctime for inodes on a |
331 | * rename. | 330 | * rename. |
332 | * inode_dec_link_count() will mark the inode dirty. | 331 | * inode_dec_link_count() will mark the inode dirty. |
333 | */ | 332 | */ |
334 | old_inode->i_ctime = CURRENT_TIME_SEC; | 333 | old_inode->i_ctime = CURRENT_TIME_SEC; |
335 | 334 | ||
336 | ufs_delete_entry(old_dir, old_de, old_page); | 335 | ufs_delete_entry(old_dir, old_de, old_page); |
337 | inode_dec_link_count(old_inode); | 336 | inode_dec_link_count(old_inode); |
338 | 337 | ||
339 | if (dir_de) { | 338 | if (dir_de) { |
340 | ufs_set_link(old_inode, dir_de, dir_page, new_dir); | 339 | ufs_set_link(old_inode, dir_de, dir_page, new_dir); |
341 | inode_dec_link_count(old_dir); | 340 | inode_dec_link_count(old_dir); |
342 | } | 341 | } |
343 | return 0; | 342 | return 0; |
344 | 343 | ||
345 | 344 | ||
346 | out_dir: | 345 | out_dir: |
347 | if (dir_de) { | 346 | if (dir_de) { |
348 | kunmap(dir_page); | 347 | kunmap(dir_page); |
349 | page_cache_release(dir_page); | 348 | page_cache_release(dir_page); |
350 | } | 349 | } |
351 | out_old: | 350 | out_old: |
352 | kunmap(old_page); | 351 | kunmap(old_page); |
353 | page_cache_release(old_page); | 352 | page_cache_release(old_page); |
354 | out: | 353 | out: |
355 | return err; | 354 | return err; |
356 | } | 355 | } |
357 | 356 | ||
358 | const struct inode_operations ufs_dir_inode_operations = { | 357 | const struct inode_operations ufs_dir_inode_operations = { |
359 | .create = ufs_create, | 358 | .create = ufs_create, |
360 | .lookup = ufs_lookup, | 359 | .lookup = ufs_lookup, |
361 | .link = ufs_link, | 360 | .link = ufs_link, |
362 | .unlink = ufs_unlink, | 361 | .unlink = ufs_unlink, |
363 | .symlink = ufs_symlink, | 362 | .symlink = ufs_symlink, |
364 | .mkdir = ufs_mkdir, | 363 | .mkdir = ufs_mkdir, |
365 | .rmdir = ufs_rmdir, | 364 | .rmdir = ufs_rmdir, |
366 | .mknod = ufs_mknod, | 365 | .mknod = ufs_mknod, |
367 | .rename = ufs_rename, | 366 | .rename = ufs_rename, |
368 | }; | 367 | }; |
369 | 368 |
fs/ufs/super.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/super.c | 2 | * linux/fs/ufs/super.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* Derived from | 9 | /* Derived from |
10 | * | 10 | * |
11 | * linux/fs/ext2/super.c | 11 | * linux/fs/ext2/super.c |
12 | * | 12 | * |
13 | * Copyright (C) 1992, 1993, 1994, 1995 | 13 | * Copyright (C) 1992, 1993, 1994, 1995 |
14 | * Remy Card (card@masi.ibp.fr) | 14 | * Remy Card (card@masi.ibp.fr) |
15 | * Laboratoire MASI - Institut Blaise Pascal | 15 | * Laboratoire MASI - Institut Blaise Pascal |
16 | * Universite Pierre et Marie Curie (Paris VI) | 16 | * Universite Pierre et Marie Curie (Paris VI) |
17 | * | 17 | * |
18 | * from | 18 | * from |
19 | * | 19 | * |
20 | * linux/fs/minix/inode.c | 20 | * linux/fs/minix/inode.c |
21 | * | 21 | * |
22 | * Copyright (C) 1991, 1992 Linus Torvalds | 22 | * Copyright (C) 1991, 1992 Linus Torvalds |
23 | * | 23 | * |
24 | * Big-endian to little-endian byte-swapping/bitmaps by | 24 | * Big-endian to little-endian byte-swapping/bitmaps by |
25 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 25 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * Inspired by | 29 | * Inspired by |
30 | * | 30 | * |
31 | * linux/fs/ufs/super.c | 31 | * linux/fs/ufs/super.c |
32 | * | 32 | * |
33 | * Copyright (C) 1996 | 33 | * Copyright (C) 1996 |
34 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) | 34 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) |
35 | * Laboratory for Computer Science Research Computing Facility | 35 | * Laboratory for Computer Science Research Computing Facility |
36 | * Rutgers, The State University of New Jersey | 36 | * Rutgers, The State University of New Jersey |
37 | * | 37 | * |
38 | * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) | 38 | * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) |
39 | * | 39 | * |
40 | * Kernel module support added on 96/04/26 by | 40 | * Kernel module support added on 96/04/26 by |
41 | * Stefan Reinauer <stepan@home.culture.mipt.ru> | 41 | * Stefan Reinauer <stepan@home.culture.mipt.ru> |
42 | * | 42 | * |
43 | * Module usage counts added on 96/04/29 by | 43 | * Module usage counts added on 96/04/29 by |
44 | * Gertjan van Wingerde <gertjan@cs.vu.nl> | 44 | * Gertjan van Wingerde <gertjan@cs.vu.nl> |
45 | * | 45 | * |
46 | * Clean swab support on 19970406 by | 46 | * Clean swab support on 19970406 by |
47 | * Francois-Rene Rideau <fare@tunes.org> | 47 | * Francois-Rene Rideau <fare@tunes.org> |
48 | * | 48 | * |
49 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by | 49 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by |
50 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based | 50 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based |
51 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. | 51 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. |
52 | * | 52 | * |
53 | * NeXTstep support added on February 5th 1998 by | 53 | * NeXTstep support added on February 5th 1998 by |
54 | * Niels Kristian Bech Jensen <nkbj@image.dk>. | 54 | * Niels Kristian Bech Jensen <nkbj@image.dk>. |
55 | * | 55 | * |
56 | * write support Daniel Pirkl <daniel.pirkl@email.cz> 1998 | 56 | * write support Daniel Pirkl <daniel.pirkl@email.cz> 1998 |
57 | * | 57 | * |
58 | * HP/UX hfs filesystem support added by | 58 | * HP/UX hfs filesystem support added by |
59 | * Martin K. Petersen <mkp@mkp.net>, August 1999 | 59 | * Martin K. Petersen <mkp@mkp.net>, August 1999 |
60 | * | 60 | * |
61 | * UFS2 (of FreeBSD 5.x) support added by | 61 | * UFS2 (of FreeBSD 5.x) support added by |
62 | * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 | 62 | * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 |
63 | * | 63 | * |
64 | * UFS2 write support added by | 64 | * UFS2 write support added by |
65 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | 65 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 |
66 | */ | 66 | */ |
67 | 67 | ||
68 | 68 | ||
69 | #include <linux/module.h> | 69 | #include <linux/module.h> |
70 | #include <linux/bitops.h> | 70 | #include <linux/bitops.h> |
71 | 71 | ||
72 | #include <stdarg.h> | 72 | #include <stdarg.h> |
73 | 73 | ||
74 | #include <asm/uaccess.h> | 74 | #include <asm/uaccess.h> |
75 | #include <asm/system.h> | 75 | #include <asm/system.h> |
76 | 76 | ||
77 | #include <linux/errno.h> | 77 | #include <linux/errno.h> |
78 | #include <linux/fs.h> | 78 | #include <linux/fs.h> |
79 | #include <linux/ufs_fs.h> | 79 | #include <linux/ufs_fs.h> |
80 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
81 | #include <linux/time.h> | 81 | #include <linux/time.h> |
82 | #include <linux/stat.h> | 82 | #include <linux/stat.h> |
83 | #include <linux/string.h> | 83 | #include <linux/string.h> |
84 | #include <linux/blkdev.h> | 84 | #include <linux/blkdev.h> |
85 | #include <linux/init.h> | 85 | #include <linux/init.h> |
86 | #include <linux/parser.h> | 86 | #include <linux/parser.h> |
87 | #include <linux/smp_lock.h> | 87 | #include <linux/smp_lock.h> |
88 | #include <linux/buffer_head.h> | 88 | #include <linux/buffer_head.h> |
89 | #include <linux/vfs.h> | 89 | #include <linux/vfs.h> |
90 | #include <linux/log2.h> | 90 | #include <linux/log2.h> |
91 | #include <linux/mount.h> | 91 | #include <linux/mount.h> |
92 | #include <linux/seq_file.h> | 92 | #include <linux/seq_file.h> |
93 | 93 | ||
94 | #include "ufs.h" | ||
94 | #include "swab.h" | 95 | #include "swab.h" |
95 | #include "util.h" | 96 | #include "util.h" |
96 | 97 | ||
97 | #ifdef CONFIG_UFS_DEBUG | 98 | #ifdef CONFIG_UFS_DEBUG |
98 | /* | 99 | /* |
99 | * Print contents of ufs_super_block, useful for debugging | 100 | * Print contents of ufs_super_block, useful for debugging |
100 | */ | 101 | */ |
101 | static void ufs_print_super_stuff(struct super_block *sb, | 102 | static void ufs_print_super_stuff(struct super_block *sb, |
102 | struct ufs_super_block_first *usb1, | 103 | struct ufs_super_block_first *usb1, |
103 | struct ufs_super_block_second *usb2, | 104 | struct ufs_super_block_second *usb2, |
104 | struct ufs_super_block_third *usb3) | 105 | struct ufs_super_block_third *usb3) |
105 | { | 106 | { |
106 | u32 magic = fs32_to_cpu(sb, usb3->fs_magic); | 107 | u32 magic = fs32_to_cpu(sb, usb3->fs_magic); |
107 | 108 | ||
108 | printk("ufs_print_super_stuff\n"); | 109 | printk("ufs_print_super_stuff\n"); |
109 | printk(" magic: 0x%x\n", magic); | 110 | printk(" magic: 0x%x\n", magic); |
110 | if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { | 111 | if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { |
111 | printk(" fs_size: %llu\n", (unsigned long long) | 112 | printk(" fs_size: %llu\n", (unsigned long long) |
112 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); | 113 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); |
113 | printk(" fs_dsize: %llu\n", (unsigned long long) | 114 | printk(" fs_dsize: %llu\n", (unsigned long long) |
114 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); | 115 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); |
115 | printk(" bsize: %u\n", | 116 | printk(" bsize: %u\n", |
116 | fs32_to_cpu(sb, usb1->fs_bsize)); | 117 | fs32_to_cpu(sb, usb1->fs_bsize)); |
117 | printk(" fsize: %u\n", | 118 | printk(" fsize: %u\n", |
118 | fs32_to_cpu(sb, usb1->fs_fsize)); | 119 | fs32_to_cpu(sb, usb1->fs_fsize)); |
119 | printk(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); | 120 | printk(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); |
120 | printk(" fs_sblockloc: %llu\n", (unsigned long long) | 121 | printk(" fs_sblockloc: %llu\n", (unsigned long long) |
121 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); | 122 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); |
122 | printk(" cs_ndir(No of dirs): %llu\n", (unsigned long long) | 123 | printk(" cs_ndir(No of dirs): %llu\n", (unsigned long long) |
123 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); | 124 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); |
124 | printk(" cs_nbfree(No of free blocks): %llu\n", | 125 | printk(" cs_nbfree(No of free blocks): %llu\n", |
125 | (unsigned long long) | 126 | (unsigned long long) |
126 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); | 127 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); |
127 | printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", | 128 | printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", |
128 | (unsigned long long) | 129 | (unsigned long long) |
129 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); | 130 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); |
130 | printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", | 131 | printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", |
131 | (unsigned long long) | 132 | (unsigned long long) |
132 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); | 133 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); |
133 | } else { | 134 | } else { |
134 | printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); | 135 | printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); |
135 | printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); | 136 | printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); |
136 | printk(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); | 137 | printk(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); |
137 | printk(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); | 138 | printk(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); |
138 | printk(" cgoffset: %u\n", | 139 | printk(" cgoffset: %u\n", |
139 | fs32_to_cpu(sb, usb1->fs_cgoffset)); | 140 | fs32_to_cpu(sb, usb1->fs_cgoffset)); |
140 | printk(" ~cgmask: 0x%x\n", | 141 | printk(" ~cgmask: 0x%x\n", |
141 | ~fs32_to_cpu(sb, usb1->fs_cgmask)); | 142 | ~fs32_to_cpu(sb, usb1->fs_cgmask)); |
142 | printk(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); | 143 | printk(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); |
143 | printk(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); | 144 | printk(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); |
144 | printk(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); | 145 | printk(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); |
145 | printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); | 146 | printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); |
146 | printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); | 147 | printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); |
147 | printk(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); | 148 | printk(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); |
148 | printk(" fragshift: %u\n", | 149 | printk(" fragshift: %u\n", |
149 | fs32_to_cpu(sb, usb1->fs_fragshift)); | 150 | fs32_to_cpu(sb, usb1->fs_fragshift)); |
150 | printk(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); | 151 | printk(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); |
151 | printk(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); | 152 | printk(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); |
152 | printk(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); | 153 | printk(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); |
153 | printk(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); | 154 | printk(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); |
154 | printk(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); | 155 | printk(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); |
155 | printk(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); | 156 | printk(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); |
156 | printk(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); | 157 | printk(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); |
157 | printk(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); | 158 | printk(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); |
158 | printk(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); | 159 | printk(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); |
159 | printk(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); | 160 | printk(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); |
160 | printk(" fstodb: %u\n", | 161 | printk(" fstodb: %u\n", |
161 | fs32_to_cpu(sb, usb1->fs_fsbtodb)); | 162 | fs32_to_cpu(sb, usb1->fs_fsbtodb)); |
162 | printk(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); | 163 | printk(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); |
163 | printk(" ndir %u\n", | 164 | printk(" ndir %u\n", |
164 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); | 165 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); |
165 | printk(" nifree %u\n", | 166 | printk(" nifree %u\n", |
166 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); | 167 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); |
167 | printk(" nbfree %u\n", | 168 | printk(" nbfree %u\n", |
168 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); | 169 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); |
169 | printk(" nffree %u\n", | 170 | printk(" nffree %u\n", |
170 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); | 171 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); |
171 | } | 172 | } |
172 | printk("\n"); | 173 | printk("\n"); |
173 | } | 174 | } |
174 | 175 | ||
175 | /* | 176 | /* |
176 | * Print contents of ufs_cylinder_group, useful for debugging | 177 | * Print contents of ufs_cylinder_group, useful for debugging |
177 | */ | 178 | */ |
178 | static void ufs_print_cylinder_stuff(struct super_block *sb, | 179 | static void ufs_print_cylinder_stuff(struct super_block *sb, |
179 | struct ufs_cylinder_group *cg) | 180 | struct ufs_cylinder_group *cg) |
180 | { | 181 | { |
181 | printk("\nufs_print_cylinder_stuff\n"); | 182 | printk("\nufs_print_cylinder_stuff\n"); |
182 | printk("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group)); | 183 | printk("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group)); |
183 | printk(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); | 184 | printk(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); |
184 | printk(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); | 185 | printk(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); |
185 | printk(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); | 186 | printk(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); |
186 | printk(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); | 187 | printk(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); |
187 | printk(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); | 188 | printk(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); |
188 | printk(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); | 189 | printk(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); |
189 | printk(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); | 190 | printk(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); |
190 | printk(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); | 191 | printk(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); |
191 | printk(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); | 192 | printk(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); |
192 | printk(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); | 193 | printk(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); |
193 | printk(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); | 194 | printk(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); |
194 | printk(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); | 195 | printk(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); |
195 | printk(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); | 196 | printk(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); |
196 | printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", | 197 | printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", |
197 | fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), | 198 | fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), |
198 | fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), | 199 | fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), |
199 | fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), | 200 | fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), |
200 | fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); | 201 | fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); |
201 | printk(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); | 202 | printk(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); |
202 | printk(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); | 203 | printk(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); |
203 | printk(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); | 204 | printk(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); |
204 | printk(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); | 205 | printk(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); |
205 | printk(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); | 206 | printk(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); |
206 | printk(" clustersumoff %u\n", | 207 | printk(" clustersumoff %u\n", |
207 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); | 208 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); |
208 | printk(" clusteroff %u\n", | 209 | printk(" clusteroff %u\n", |
209 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); | 210 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); |
210 | printk(" nclusterblks %u\n", | 211 | printk(" nclusterblks %u\n", |
211 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); | 212 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); |
212 | printk("\n"); | 213 | printk("\n"); |
213 | } | 214 | } |
214 | #else | 215 | #else |
215 | # define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ | 216 | # define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ |
216 | # define ufs_print_cylinder_stuff(sb, cg) /**/ | 217 | # define ufs_print_cylinder_stuff(sb, cg) /**/ |
217 | #endif /* CONFIG_UFS_DEBUG */ | 218 | #endif /* CONFIG_UFS_DEBUG */ |
218 | 219 | ||
219 | static const struct super_operations ufs_super_ops; | 220 | static const struct super_operations ufs_super_ops; |
220 | 221 | ||
221 | static char error_buf[1024]; | 222 | static char error_buf[1024]; |
222 | 223 | ||
223 | void ufs_error (struct super_block * sb, const char * function, | 224 | void ufs_error (struct super_block * sb, const char * function, |
224 | const char * fmt, ...) | 225 | const char * fmt, ...) |
225 | { | 226 | { |
226 | struct ufs_sb_private_info * uspi; | 227 | struct ufs_sb_private_info * uspi; |
227 | struct ufs_super_block_first * usb1; | 228 | struct ufs_super_block_first * usb1; |
228 | va_list args; | 229 | va_list args; |
229 | 230 | ||
230 | uspi = UFS_SB(sb)->s_uspi; | 231 | uspi = UFS_SB(sb)->s_uspi; |
231 | usb1 = ubh_get_usb_first(uspi); | 232 | usb1 = ubh_get_usb_first(uspi); |
232 | 233 | ||
233 | if (!(sb->s_flags & MS_RDONLY)) { | 234 | if (!(sb->s_flags & MS_RDONLY)) { |
234 | usb1->fs_clean = UFS_FSBAD; | 235 | usb1->fs_clean = UFS_FSBAD; |
235 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 236 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
236 | sb->s_dirt = 1; | 237 | sb->s_dirt = 1; |
237 | sb->s_flags |= MS_RDONLY; | 238 | sb->s_flags |= MS_RDONLY; |
238 | } | 239 | } |
239 | va_start (args, fmt); | 240 | va_start (args, fmt); |
240 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 241 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); |
241 | va_end (args); | 242 | va_end (args); |
242 | switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { | 243 | switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { |
243 | case UFS_MOUNT_ONERROR_PANIC: | 244 | case UFS_MOUNT_ONERROR_PANIC: |
244 | panic ("UFS-fs panic (device %s): %s: %s\n", | 245 | panic ("UFS-fs panic (device %s): %s: %s\n", |
245 | sb->s_id, function, error_buf); | 246 | sb->s_id, function, error_buf); |
246 | 247 | ||
247 | case UFS_MOUNT_ONERROR_LOCK: | 248 | case UFS_MOUNT_ONERROR_LOCK: |
248 | case UFS_MOUNT_ONERROR_UMOUNT: | 249 | case UFS_MOUNT_ONERROR_UMOUNT: |
249 | case UFS_MOUNT_ONERROR_REPAIR: | 250 | case UFS_MOUNT_ONERROR_REPAIR: |
250 | printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", | 251 | printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", |
251 | sb->s_id, function, error_buf); | 252 | sb->s_id, function, error_buf); |
252 | } | 253 | } |
253 | } | 254 | } |
254 | 255 | ||
255 | void ufs_panic (struct super_block * sb, const char * function, | 256 | void ufs_panic (struct super_block * sb, const char * function, |
256 | const char * fmt, ...) | 257 | const char * fmt, ...) |
257 | { | 258 | { |
258 | struct ufs_sb_private_info * uspi; | 259 | struct ufs_sb_private_info * uspi; |
259 | struct ufs_super_block_first * usb1; | 260 | struct ufs_super_block_first * usb1; |
260 | va_list args; | 261 | va_list args; |
261 | 262 | ||
262 | uspi = UFS_SB(sb)->s_uspi; | 263 | uspi = UFS_SB(sb)->s_uspi; |
263 | usb1 = ubh_get_usb_first(uspi); | 264 | usb1 = ubh_get_usb_first(uspi); |
264 | 265 | ||
265 | if (!(sb->s_flags & MS_RDONLY)) { | 266 | if (!(sb->s_flags & MS_RDONLY)) { |
266 | usb1->fs_clean = UFS_FSBAD; | 267 | usb1->fs_clean = UFS_FSBAD; |
267 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 268 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
268 | sb->s_dirt = 1; | 269 | sb->s_dirt = 1; |
269 | } | 270 | } |
270 | va_start (args, fmt); | 271 | va_start (args, fmt); |
271 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 272 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); |
272 | va_end (args); | 273 | va_end (args); |
273 | sb->s_flags |= MS_RDONLY; | 274 | sb->s_flags |= MS_RDONLY; |
274 | printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", | 275 | printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", |
275 | sb->s_id, function, error_buf); | 276 | sb->s_id, function, error_buf); |
276 | } | 277 | } |
277 | 278 | ||
278 | void ufs_warning (struct super_block * sb, const char * function, | 279 | void ufs_warning (struct super_block * sb, const char * function, |
279 | const char * fmt, ...) | 280 | const char * fmt, ...) |
280 | { | 281 | { |
281 | va_list args; | 282 | va_list args; |
282 | 283 | ||
283 | va_start (args, fmt); | 284 | va_start (args, fmt); |
284 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 285 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); |
285 | va_end (args); | 286 | va_end (args); |
286 | printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", | 287 | printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", |
287 | sb->s_id, function, error_buf); | 288 | sb->s_id, function, error_buf); |
288 | } | 289 | } |
289 | 290 | ||
290 | enum { | 291 | enum { |
291 | Opt_type_old = UFS_MOUNT_UFSTYPE_OLD, | 292 | Opt_type_old = UFS_MOUNT_UFSTYPE_OLD, |
292 | Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86, | 293 | Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86, |
293 | Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN, | 294 | Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN, |
294 | Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS, | 295 | Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS, |
295 | Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD, | 296 | Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD, |
296 | Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2, | 297 | Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2, |
297 | Opt_type_hp = UFS_MOUNT_UFSTYPE_HP, | 298 | Opt_type_hp = UFS_MOUNT_UFSTYPE_HP, |
298 | Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD, | 299 | Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD, |
299 | Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP, | 300 | Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP, |
300 | Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP, | 301 | Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP, |
301 | Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC, | 302 | Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC, |
302 | Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK, | 303 | Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK, |
303 | Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT, | 304 | Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT, |
304 | Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR, | 305 | Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR, |
305 | Opt_err | 306 | Opt_err |
306 | }; | 307 | }; |
307 | 308 | ||
308 | static match_table_t tokens = { | 309 | static match_table_t tokens = { |
309 | {Opt_type_old, "ufstype=old"}, | 310 | {Opt_type_old, "ufstype=old"}, |
310 | {Opt_type_sunx86, "ufstype=sunx86"}, | 311 | {Opt_type_sunx86, "ufstype=sunx86"}, |
311 | {Opt_type_sun, "ufstype=sun"}, | 312 | {Opt_type_sun, "ufstype=sun"}, |
312 | {Opt_type_sunos, "ufstype=sunos"}, | 313 | {Opt_type_sunos, "ufstype=sunos"}, |
313 | {Opt_type_44bsd, "ufstype=44bsd"}, | 314 | {Opt_type_44bsd, "ufstype=44bsd"}, |
314 | {Opt_type_ufs2, "ufstype=ufs2"}, | 315 | {Opt_type_ufs2, "ufstype=ufs2"}, |
315 | {Opt_type_ufs2, "ufstype=5xbsd"}, | 316 | {Opt_type_ufs2, "ufstype=5xbsd"}, |
316 | {Opt_type_hp, "ufstype=hp"}, | 317 | {Opt_type_hp, "ufstype=hp"}, |
317 | {Opt_type_nextstepcd, "ufstype=nextstep-cd"}, | 318 | {Opt_type_nextstepcd, "ufstype=nextstep-cd"}, |
318 | {Opt_type_nextstep, "ufstype=nextstep"}, | 319 | {Opt_type_nextstep, "ufstype=nextstep"}, |
319 | {Opt_type_openstep, "ufstype=openstep"}, | 320 | {Opt_type_openstep, "ufstype=openstep"}, |
320 | /*end of possible ufs types */ | 321 | /*end of possible ufs types */ |
321 | {Opt_onerror_panic, "onerror=panic"}, | 322 | {Opt_onerror_panic, "onerror=panic"}, |
322 | {Opt_onerror_lock, "onerror=lock"}, | 323 | {Opt_onerror_lock, "onerror=lock"}, |
323 | {Opt_onerror_umount, "onerror=umount"}, | 324 | {Opt_onerror_umount, "onerror=umount"}, |
324 | {Opt_onerror_repair, "onerror=repair"}, | 325 | {Opt_onerror_repair, "onerror=repair"}, |
325 | {Opt_err, NULL} | 326 | {Opt_err, NULL} |
326 | }; | 327 | }; |
327 | 328 | ||
328 | static int ufs_parse_options (char * options, unsigned * mount_options) | 329 | static int ufs_parse_options (char * options, unsigned * mount_options) |
329 | { | 330 | { |
330 | char * p; | 331 | char * p; |
331 | 332 | ||
332 | UFSD("ENTER\n"); | 333 | UFSD("ENTER\n"); |
333 | 334 | ||
334 | if (!options) | 335 | if (!options) |
335 | return 1; | 336 | return 1; |
336 | 337 | ||
337 | while ((p = strsep(&options, ",")) != NULL) { | 338 | while ((p = strsep(&options, ",")) != NULL) { |
338 | substring_t args[MAX_OPT_ARGS]; | 339 | substring_t args[MAX_OPT_ARGS]; |
339 | int token; | 340 | int token; |
340 | if (!*p) | 341 | if (!*p) |
341 | continue; | 342 | continue; |
342 | 343 | ||
343 | token = match_token(p, tokens, args); | 344 | token = match_token(p, tokens, args); |
344 | switch (token) { | 345 | switch (token) { |
345 | case Opt_type_old: | 346 | case Opt_type_old: |
346 | ufs_clear_opt (*mount_options, UFSTYPE); | 347 | ufs_clear_opt (*mount_options, UFSTYPE); |
347 | ufs_set_opt (*mount_options, UFSTYPE_OLD); | 348 | ufs_set_opt (*mount_options, UFSTYPE_OLD); |
348 | break; | 349 | break; |
349 | case Opt_type_sunx86: | 350 | case Opt_type_sunx86: |
350 | ufs_clear_opt (*mount_options, UFSTYPE); | 351 | ufs_clear_opt (*mount_options, UFSTYPE); |
351 | ufs_set_opt (*mount_options, UFSTYPE_SUNx86); | 352 | ufs_set_opt (*mount_options, UFSTYPE_SUNx86); |
352 | break; | 353 | break; |
353 | case Opt_type_sun: | 354 | case Opt_type_sun: |
354 | ufs_clear_opt (*mount_options, UFSTYPE); | 355 | ufs_clear_opt (*mount_options, UFSTYPE); |
355 | ufs_set_opt (*mount_options, UFSTYPE_SUN); | 356 | ufs_set_opt (*mount_options, UFSTYPE_SUN); |
356 | break; | 357 | break; |
357 | case Opt_type_sunos: | 358 | case Opt_type_sunos: |
358 | ufs_clear_opt(*mount_options, UFSTYPE); | 359 | ufs_clear_opt(*mount_options, UFSTYPE); |
359 | ufs_set_opt(*mount_options, UFSTYPE_SUNOS); | 360 | ufs_set_opt(*mount_options, UFSTYPE_SUNOS); |
360 | break; | 361 | break; |
361 | case Opt_type_44bsd: | 362 | case Opt_type_44bsd: |
362 | ufs_clear_opt (*mount_options, UFSTYPE); | 363 | ufs_clear_opt (*mount_options, UFSTYPE); |
363 | ufs_set_opt (*mount_options, UFSTYPE_44BSD); | 364 | ufs_set_opt (*mount_options, UFSTYPE_44BSD); |
364 | break; | 365 | break; |
365 | case Opt_type_ufs2: | 366 | case Opt_type_ufs2: |
366 | ufs_clear_opt(*mount_options, UFSTYPE); | 367 | ufs_clear_opt(*mount_options, UFSTYPE); |
367 | ufs_set_opt(*mount_options, UFSTYPE_UFS2); | 368 | ufs_set_opt(*mount_options, UFSTYPE_UFS2); |
368 | break; | 369 | break; |
369 | case Opt_type_hp: | 370 | case Opt_type_hp: |
370 | ufs_clear_opt (*mount_options, UFSTYPE); | 371 | ufs_clear_opt (*mount_options, UFSTYPE); |
371 | ufs_set_opt (*mount_options, UFSTYPE_HP); | 372 | ufs_set_opt (*mount_options, UFSTYPE_HP); |
372 | break; | 373 | break; |
373 | case Opt_type_nextstepcd: | 374 | case Opt_type_nextstepcd: |
374 | ufs_clear_opt (*mount_options, UFSTYPE); | 375 | ufs_clear_opt (*mount_options, UFSTYPE); |
375 | ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD); | 376 | ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD); |
376 | break; | 377 | break; |
377 | case Opt_type_nextstep: | 378 | case Opt_type_nextstep: |
378 | ufs_clear_opt (*mount_options, UFSTYPE); | 379 | ufs_clear_opt (*mount_options, UFSTYPE); |
379 | ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP); | 380 | ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP); |
380 | break; | 381 | break; |
381 | case Opt_type_openstep: | 382 | case Opt_type_openstep: |
382 | ufs_clear_opt (*mount_options, UFSTYPE); | 383 | ufs_clear_opt (*mount_options, UFSTYPE); |
383 | ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); | 384 | ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); |
384 | break; | 385 | break; |
385 | case Opt_onerror_panic: | 386 | case Opt_onerror_panic: |
386 | ufs_clear_opt (*mount_options, ONERROR); | 387 | ufs_clear_opt (*mount_options, ONERROR); |
387 | ufs_set_opt (*mount_options, ONERROR_PANIC); | 388 | ufs_set_opt (*mount_options, ONERROR_PANIC); |
388 | break; | 389 | break; |
389 | case Opt_onerror_lock: | 390 | case Opt_onerror_lock: |
390 | ufs_clear_opt (*mount_options, ONERROR); | 391 | ufs_clear_opt (*mount_options, ONERROR); |
391 | ufs_set_opt (*mount_options, ONERROR_LOCK); | 392 | ufs_set_opt (*mount_options, ONERROR_LOCK); |
392 | break; | 393 | break; |
393 | case Opt_onerror_umount: | 394 | case Opt_onerror_umount: |
394 | ufs_clear_opt (*mount_options, ONERROR); | 395 | ufs_clear_opt (*mount_options, ONERROR); |
395 | ufs_set_opt (*mount_options, ONERROR_UMOUNT); | 396 | ufs_set_opt (*mount_options, ONERROR_UMOUNT); |
396 | break; | 397 | break; |
397 | case Opt_onerror_repair: | 398 | case Opt_onerror_repair: |
398 | printk("UFS-fs: Unable to do repair on error, " | 399 | printk("UFS-fs: Unable to do repair on error, " |
399 | "will lock lock instead\n"); | 400 | "will lock lock instead\n"); |
400 | ufs_clear_opt (*mount_options, ONERROR); | 401 | ufs_clear_opt (*mount_options, ONERROR); |
401 | ufs_set_opt (*mount_options, ONERROR_REPAIR); | 402 | ufs_set_opt (*mount_options, ONERROR_REPAIR); |
402 | break; | 403 | break; |
403 | default: | 404 | default: |
404 | printk("UFS-fs: Invalid option: \"%s\" " | 405 | printk("UFS-fs: Invalid option: \"%s\" " |
405 | "or missing value\n", p); | 406 | "or missing value\n", p); |
406 | return 0; | 407 | return 0; |
407 | } | 408 | } |
408 | } | 409 | } |
409 | return 1; | 410 | return 1; |
410 | } | 411 | } |
411 | 412 | ||
412 | /* | 413 | /* |
413 | * Diffrent types of UFS hold fs_cstotal in different | 414 | * Diffrent types of UFS hold fs_cstotal in different |
414 | * places, and use diffrent data structure for it. | 415 | * places, and use diffrent data structure for it. |
415 | * To make things simplier we just copy fs_cstotal to ufs_sb_private_info | 416 | * To make things simplier we just copy fs_cstotal to ufs_sb_private_info |
416 | */ | 417 | */ |
417 | static void ufs_setup_cstotal(struct super_block *sb) | 418 | static void ufs_setup_cstotal(struct super_block *sb) |
418 | { | 419 | { |
419 | struct ufs_sb_info *sbi = UFS_SB(sb); | 420 | struct ufs_sb_info *sbi = UFS_SB(sb); |
420 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | 421 | struct ufs_sb_private_info *uspi = sbi->s_uspi; |
421 | struct ufs_super_block_first *usb1; | 422 | struct ufs_super_block_first *usb1; |
422 | struct ufs_super_block_second *usb2; | 423 | struct ufs_super_block_second *usb2; |
423 | struct ufs_super_block_third *usb3; | 424 | struct ufs_super_block_third *usb3; |
424 | unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; | 425 | unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; |
425 | 426 | ||
426 | UFSD("ENTER, mtype=%u\n", mtype); | 427 | UFSD("ENTER, mtype=%u\n", mtype); |
427 | usb1 = ubh_get_usb_first(uspi); | 428 | usb1 = ubh_get_usb_first(uspi); |
428 | usb2 = ubh_get_usb_second(uspi); | 429 | usb2 = ubh_get_usb_second(uspi); |
429 | usb3 = ubh_get_usb_third(uspi); | 430 | usb3 = ubh_get_usb_third(uspi); |
430 | 431 | ||
431 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && | 432 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && |
432 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || | 433 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || |
433 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { | 434 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { |
434 | /*we have statistic in different place, then usual*/ | 435 | /*we have statistic in different place, then usual*/ |
435 | uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); | 436 | uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); |
436 | uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree); | 437 | uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree); |
437 | uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); | 438 | uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); |
438 | uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); | 439 | uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); |
439 | } else { | 440 | } else { |
440 | uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir); | 441 | uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir); |
441 | uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree); | 442 | uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree); |
442 | uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); | 443 | uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); |
443 | uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); | 444 | uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); |
444 | } | 445 | } |
445 | UFSD("EXIT\n"); | 446 | UFSD("EXIT\n"); |
446 | } | 447 | } |
447 | 448 | ||
448 | /* | 449 | /* |
449 | * Read on-disk structures associated with cylinder groups | 450 | * Read on-disk structures associated with cylinder groups |
450 | */ | 451 | */ |
451 | static int ufs_read_cylinder_structures(struct super_block *sb) | 452 | static int ufs_read_cylinder_structures(struct super_block *sb) |
452 | { | 453 | { |
453 | struct ufs_sb_info *sbi = UFS_SB(sb); | 454 | struct ufs_sb_info *sbi = UFS_SB(sb); |
454 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | 455 | struct ufs_sb_private_info *uspi = sbi->s_uspi; |
455 | struct ufs_buffer_head * ubh; | 456 | struct ufs_buffer_head * ubh; |
456 | unsigned char * base, * space; | 457 | unsigned char * base, * space; |
457 | unsigned size, blks, i; | 458 | unsigned size, blks, i; |
458 | struct ufs_super_block_third *usb3; | 459 | struct ufs_super_block_third *usb3; |
459 | 460 | ||
460 | UFSD("ENTER\n"); | 461 | UFSD("ENTER\n"); |
461 | 462 | ||
462 | usb3 = ubh_get_usb_third(uspi); | 463 | usb3 = ubh_get_usb_third(uspi); |
463 | /* | 464 | /* |
464 | * Read cs structures from (usually) first data block | 465 | * Read cs structures from (usually) first data block |
465 | * on the device. | 466 | * on the device. |
466 | */ | 467 | */ |
467 | size = uspi->s_cssize; | 468 | size = uspi->s_cssize; |
468 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; | 469 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; |
469 | base = space = kmalloc(size, GFP_KERNEL); | 470 | base = space = kmalloc(size, GFP_KERNEL); |
470 | if (!base) | 471 | if (!base) |
471 | goto failed; | 472 | goto failed; |
472 | sbi->s_csp = (struct ufs_csum *)space; | 473 | sbi->s_csp = (struct ufs_csum *)space; |
473 | for (i = 0; i < blks; i += uspi->s_fpb) { | 474 | for (i = 0; i < blks; i += uspi->s_fpb) { |
474 | size = uspi->s_bsize; | 475 | size = uspi->s_bsize; |
475 | if (i + uspi->s_fpb > blks) | 476 | if (i + uspi->s_fpb > blks) |
476 | size = (blks - i) * uspi->s_fsize; | 477 | size = (blks - i) * uspi->s_fsize; |
477 | 478 | ||
478 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); | 479 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); |
479 | 480 | ||
480 | if (!ubh) | 481 | if (!ubh) |
481 | goto failed; | 482 | goto failed; |
482 | 483 | ||
483 | ubh_ubhcpymem (space, ubh, size); | 484 | ubh_ubhcpymem (space, ubh, size); |
484 | 485 | ||
485 | space += size; | 486 | space += size; |
486 | ubh_brelse (ubh); | 487 | ubh_brelse (ubh); |
487 | ubh = NULL; | 488 | ubh = NULL; |
488 | } | 489 | } |
489 | 490 | ||
490 | /* | 491 | /* |
491 | * Read cylinder group (we read only first fragment from block | 492 | * Read cylinder group (we read only first fragment from block |
492 | * at this time) and prepare internal data structures for cg caching. | 493 | * at this time) and prepare internal data structures for cg caching. |
493 | */ | 494 | */ |
494 | if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) | 495 | if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) |
495 | goto failed; | 496 | goto failed; |
496 | for (i = 0; i < uspi->s_ncg; i++) | 497 | for (i = 0; i < uspi->s_ncg; i++) |
497 | sbi->s_ucg[i] = NULL; | 498 | sbi->s_ucg[i] = NULL; |
498 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { | 499 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { |
499 | sbi->s_ucpi[i] = NULL; | 500 | sbi->s_ucpi[i] = NULL; |
500 | sbi->s_cgno[i] = UFS_CGNO_EMPTY; | 501 | sbi->s_cgno[i] = UFS_CGNO_EMPTY; |
501 | } | 502 | } |
502 | for (i = 0; i < uspi->s_ncg; i++) { | 503 | for (i = 0; i < uspi->s_ncg; i++) { |
503 | UFSD("read cg %u\n", i); | 504 | UFSD("read cg %u\n", i); |
504 | if (!(sbi->s_ucg[i] = sb_bread(sb, ufs_cgcmin(i)))) | 505 | if (!(sbi->s_ucg[i] = sb_bread(sb, ufs_cgcmin(i)))) |
505 | goto failed; | 506 | goto failed; |
506 | if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data)) | 507 | if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data)) |
507 | goto failed; | 508 | goto failed; |
508 | 509 | ||
509 | ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data); | 510 | ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data); |
510 | } | 511 | } |
511 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { | 512 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { |
512 | if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) | 513 | if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) |
513 | goto failed; | 514 | goto failed; |
514 | sbi->s_cgno[i] = UFS_CGNO_EMPTY; | 515 | sbi->s_cgno[i] = UFS_CGNO_EMPTY; |
515 | } | 516 | } |
516 | sbi->s_cg_loaded = 0; | 517 | sbi->s_cg_loaded = 0; |
517 | UFSD("EXIT\n"); | 518 | UFSD("EXIT\n"); |
518 | return 1; | 519 | return 1; |
519 | 520 | ||
520 | failed: | 521 | failed: |
521 | kfree (base); | 522 | kfree (base); |
522 | if (sbi->s_ucg) { | 523 | if (sbi->s_ucg) { |
523 | for (i = 0; i < uspi->s_ncg; i++) | 524 | for (i = 0; i < uspi->s_ncg; i++) |
524 | if (sbi->s_ucg[i]) | 525 | if (sbi->s_ucg[i]) |
525 | brelse (sbi->s_ucg[i]); | 526 | brelse (sbi->s_ucg[i]); |
526 | kfree (sbi->s_ucg); | 527 | kfree (sbi->s_ucg); |
527 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) | 528 | for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) |
528 | kfree (sbi->s_ucpi[i]); | 529 | kfree (sbi->s_ucpi[i]); |
529 | } | 530 | } |
530 | UFSD("EXIT (FAILED)\n"); | 531 | UFSD("EXIT (FAILED)\n"); |
531 | return 0; | 532 | return 0; |
532 | } | 533 | } |
533 | 534 | ||
534 | /* | 535 | /* |
535 | * Sync our internal copy of fs_cstotal with disk | 536 | * Sync our internal copy of fs_cstotal with disk |
536 | */ | 537 | */ |
537 | static void ufs_put_cstotal(struct super_block *sb) | 538 | static void ufs_put_cstotal(struct super_block *sb) |
538 | { | 539 | { |
539 | unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; | 540 | unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; |
540 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 541 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
541 | struct ufs_super_block_first *usb1; | 542 | struct ufs_super_block_first *usb1; |
542 | struct ufs_super_block_second *usb2; | 543 | struct ufs_super_block_second *usb2; |
543 | struct ufs_super_block_third *usb3; | 544 | struct ufs_super_block_third *usb3; |
544 | 545 | ||
545 | UFSD("ENTER\n"); | 546 | UFSD("ENTER\n"); |
546 | usb1 = ubh_get_usb_first(uspi); | 547 | usb1 = ubh_get_usb_first(uspi); |
547 | usb2 = ubh_get_usb_second(uspi); | 548 | usb2 = ubh_get_usb_second(uspi); |
548 | usb3 = ubh_get_usb_third(uspi); | 549 | usb3 = ubh_get_usb_third(uspi); |
549 | 550 | ||
550 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && | 551 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && |
551 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || | 552 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || |
552 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { | 553 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { |
553 | /*we have statistic in different place, then usual*/ | 554 | /*we have statistic in different place, then usual*/ |
554 | usb2->fs_un.fs_u2.cs_ndir = | 555 | usb2->fs_un.fs_u2.cs_ndir = |
555 | cpu_to_fs64(sb, uspi->cs_total.cs_ndir); | 556 | cpu_to_fs64(sb, uspi->cs_total.cs_ndir); |
556 | usb2->fs_un.fs_u2.cs_nbfree = | 557 | usb2->fs_un.fs_u2.cs_nbfree = |
557 | cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); | 558 | cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); |
558 | usb3->fs_un1.fs_u2.cs_nifree = | 559 | usb3->fs_un1.fs_u2.cs_nifree = |
559 | cpu_to_fs64(sb, uspi->cs_total.cs_nifree); | 560 | cpu_to_fs64(sb, uspi->cs_total.cs_nifree); |
560 | usb3->fs_un1.fs_u2.cs_nffree = | 561 | usb3->fs_un1.fs_u2.cs_nffree = |
561 | cpu_to_fs64(sb, uspi->cs_total.cs_nffree); | 562 | cpu_to_fs64(sb, uspi->cs_total.cs_nffree); |
562 | } else { | 563 | } else { |
563 | usb1->fs_cstotal.cs_ndir = | 564 | usb1->fs_cstotal.cs_ndir = |
564 | cpu_to_fs32(sb, uspi->cs_total.cs_ndir); | 565 | cpu_to_fs32(sb, uspi->cs_total.cs_ndir); |
565 | usb1->fs_cstotal.cs_nbfree = | 566 | usb1->fs_cstotal.cs_nbfree = |
566 | cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); | 567 | cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); |
567 | usb1->fs_cstotal.cs_nifree = | 568 | usb1->fs_cstotal.cs_nifree = |
568 | cpu_to_fs32(sb, uspi->cs_total.cs_nifree); | 569 | cpu_to_fs32(sb, uspi->cs_total.cs_nifree); |
569 | usb1->fs_cstotal.cs_nffree = | 570 | usb1->fs_cstotal.cs_nffree = |
570 | cpu_to_fs32(sb, uspi->cs_total.cs_nffree); | 571 | cpu_to_fs32(sb, uspi->cs_total.cs_nffree); |
571 | } | 572 | } |
572 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 573 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
573 | ufs_print_super_stuff(sb, usb1, usb2, usb3); | 574 | ufs_print_super_stuff(sb, usb1, usb2, usb3); |
574 | UFSD("EXIT\n"); | 575 | UFSD("EXIT\n"); |
575 | } | 576 | } |
576 | 577 | ||
577 | /** | 578 | /** |
578 | * ufs_put_super_internal() - put on-disk intrenal structures | 579 | * ufs_put_super_internal() - put on-disk intrenal structures |
579 | * @sb: pointer to super_block structure | 580 | * @sb: pointer to super_block structure |
580 | * Put on-disk structures associated with cylinder groups | 581 | * Put on-disk structures associated with cylinder groups |
581 | * and write them back to disk, also update cs_total on disk | 582 | * and write them back to disk, also update cs_total on disk |
582 | */ | 583 | */ |
583 | static void ufs_put_super_internal(struct super_block *sb) | 584 | static void ufs_put_super_internal(struct super_block *sb) |
584 | { | 585 | { |
585 | struct ufs_sb_info *sbi = UFS_SB(sb); | 586 | struct ufs_sb_info *sbi = UFS_SB(sb); |
586 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | 587 | struct ufs_sb_private_info *uspi = sbi->s_uspi; |
587 | struct ufs_buffer_head * ubh; | 588 | struct ufs_buffer_head * ubh; |
588 | unsigned char * base, * space; | 589 | unsigned char * base, * space; |
589 | unsigned blks, size, i; | 590 | unsigned blks, size, i; |
590 | 591 | ||
591 | 592 | ||
592 | UFSD("ENTER\n"); | 593 | UFSD("ENTER\n"); |
593 | ufs_put_cstotal(sb); | 594 | ufs_put_cstotal(sb); |
594 | size = uspi->s_cssize; | 595 | size = uspi->s_cssize; |
595 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; | 596 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; |
596 | base = space = (char*) sbi->s_csp; | 597 | base = space = (char*) sbi->s_csp; |
597 | for (i = 0; i < blks; i += uspi->s_fpb) { | 598 | for (i = 0; i < blks; i += uspi->s_fpb) { |
598 | size = uspi->s_bsize; | 599 | size = uspi->s_bsize; |
599 | if (i + uspi->s_fpb > blks) | 600 | if (i + uspi->s_fpb > blks) |
600 | size = (blks - i) * uspi->s_fsize; | 601 | size = (blks - i) * uspi->s_fsize; |
601 | 602 | ||
602 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); | 603 | ubh = ubh_bread(sb, uspi->s_csaddr + i, size); |
603 | 604 | ||
604 | ubh_memcpyubh (ubh, space, size); | 605 | ubh_memcpyubh (ubh, space, size); |
605 | space += size; | 606 | space += size; |
606 | ubh_mark_buffer_uptodate (ubh, 1); | 607 | ubh_mark_buffer_uptodate (ubh, 1); |
607 | ubh_mark_buffer_dirty (ubh); | 608 | ubh_mark_buffer_dirty (ubh); |
608 | ubh_brelse (ubh); | 609 | ubh_brelse (ubh); |
609 | } | 610 | } |
610 | for (i = 0; i < sbi->s_cg_loaded; i++) { | 611 | for (i = 0; i < sbi->s_cg_loaded; i++) { |
611 | ufs_put_cylinder (sb, i); | 612 | ufs_put_cylinder (sb, i); |
612 | kfree (sbi->s_ucpi[i]); | 613 | kfree (sbi->s_ucpi[i]); |
613 | } | 614 | } |
614 | for (; i < UFS_MAX_GROUP_LOADED; i++) | 615 | for (; i < UFS_MAX_GROUP_LOADED; i++) |
615 | kfree (sbi->s_ucpi[i]); | 616 | kfree (sbi->s_ucpi[i]); |
616 | for (i = 0; i < uspi->s_ncg; i++) | 617 | for (i = 0; i < uspi->s_ncg; i++) |
617 | brelse (sbi->s_ucg[i]); | 618 | brelse (sbi->s_ucg[i]); |
618 | kfree (sbi->s_ucg); | 619 | kfree (sbi->s_ucg); |
619 | kfree (base); | 620 | kfree (base); |
620 | UFSD("EXIT\n"); | 621 | UFSD("EXIT\n"); |
621 | } | 622 | } |
622 | 623 | ||
623 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) | 624 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) |
624 | { | 625 | { |
625 | struct ufs_sb_info * sbi; | 626 | struct ufs_sb_info * sbi; |
626 | struct ufs_sb_private_info * uspi; | 627 | struct ufs_sb_private_info * uspi; |
627 | struct ufs_super_block_first * usb1; | 628 | struct ufs_super_block_first * usb1; |
628 | struct ufs_super_block_second * usb2; | 629 | struct ufs_super_block_second * usb2; |
629 | struct ufs_super_block_third * usb3; | 630 | struct ufs_super_block_third * usb3; |
630 | struct ufs_buffer_head * ubh; | 631 | struct ufs_buffer_head * ubh; |
631 | struct inode *inode; | 632 | struct inode *inode; |
632 | unsigned block_size, super_block_size; | 633 | unsigned block_size, super_block_size; |
633 | unsigned flags; | 634 | unsigned flags; |
634 | unsigned super_block_offset; | 635 | unsigned super_block_offset; |
635 | 636 | ||
636 | uspi = NULL; | 637 | uspi = NULL; |
637 | ubh = NULL; | 638 | ubh = NULL; |
638 | flags = 0; | 639 | flags = 0; |
639 | 640 | ||
640 | UFSD("ENTER\n"); | 641 | UFSD("ENTER\n"); |
641 | 642 | ||
642 | sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL); | 643 | sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL); |
643 | if (!sbi) | 644 | if (!sbi) |
644 | goto failed_nomem; | 645 | goto failed_nomem; |
645 | sb->s_fs_info = sbi; | 646 | sb->s_fs_info = sbi; |
646 | 647 | ||
647 | UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); | 648 | UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); |
648 | 649 | ||
649 | #ifndef CONFIG_UFS_FS_WRITE | 650 | #ifndef CONFIG_UFS_FS_WRITE |
650 | if (!(sb->s_flags & MS_RDONLY)) { | 651 | if (!(sb->s_flags & MS_RDONLY)) { |
651 | printk("ufs was compiled with read-only support, " | 652 | printk("ufs was compiled with read-only support, " |
652 | "can't be mounted as read-write\n"); | 653 | "can't be mounted as read-write\n"); |
653 | goto failed; | 654 | goto failed; |
654 | } | 655 | } |
655 | #endif | 656 | #endif |
656 | /* | 657 | /* |
657 | * Set default mount options | 658 | * Set default mount options |
658 | * Parse mount options | 659 | * Parse mount options |
659 | */ | 660 | */ |
660 | sbi->s_mount_opt = 0; | 661 | sbi->s_mount_opt = 0; |
661 | ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK); | 662 | ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK); |
662 | if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) { | 663 | if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) { |
663 | printk("wrong mount options\n"); | 664 | printk("wrong mount options\n"); |
664 | goto failed; | 665 | goto failed; |
665 | } | 666 | } |
666 | if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) { | 667 | if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) { |
667 | if (!silent) | 668 | if (!silent) |
668 | printk("You didn't specify the type of your ufs filesystem\n\n" | 669 | printk("You didn't specify the type of your ufs filesystem\n\n" |
669 | "mount -t ufs -o ufstype=" | 670 | "mount -t ufs -o ufstype=" |
670 | "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n" | 671 | "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n" |
671 | ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " | 672 | ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " |
672 | "default is ufstype=old\n"); | 673 | "default is ufstype=old\n"); |
673 | ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD); | 674 | ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD); |
674 | } | 675 | } |
675 | 676 | ||
676 | uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL); | 677 | uspi = kzalloc(sizeof(struct ufs_sb_private_info), GFP_KERNEL); |
677 | sbi->s_uspi = uspi; | 678 | sbi->s_uspi = uspi; |
678 | if (!uspi) | 679 | if (!uspi) |
679 | goto failed; | 680 | goto failed; |
680 | uspi->s_dirblksize = UFS_SECTOR_SIZE; | 681 | uspi->s_dirblksize = UFS_SECTOR_SIZE; |
681 | super_block_offset=UFS_SBLOCK; | 682 | super_block_offset=UFS_SBLOCK; |
682 | 683 | ||
683 | /* Keep 2Gig file limit. Some UFS variants need to override | 684 | /* Keep 2Gig file limit. Some UFS variants need to override |
684 | this but as I don't know which I'll let those in the know loosen | 685 | this but as I don't know which I'll let those in the know loosen |
685 | the rules */ | 686 | the rules */ |
686 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { | 687 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { |
687 | case UFS_MOUNT_UFSTYPE_44BSD: | 688 | case UFS_MOUNT_UFSTYPE_44BSD: |
688 | UFSD("ufstype=44bsd\n"); | 689 | UFSD("ufstype=44bsd\n"); |
689 | uspi->s_fsize = block_size = 512; | 690 | uspi->s_fsize = block_size = 512; |
690 | uspi->s_fmask = ~(512 - 1); | 691 | uspi->s_fmask = ~(512 - 1); |
691 | uspi->s_fshift = 9; | 692 | uspi->s_fshift = 9; |
692 | uspi->s_sbsize = super_block_size = 1536; | 693 | uspi->s_sbsize = super_block_size = 1536; |
693 | uspi->s_sbbase = 0; | 694 | uspi->s_sbbase = 0; |
694 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 695 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
695 | break; | 696 | break; |
696 | case UFS_MOUNT_UFSTYPE_UFS2: | 697 | case UFS_MOUNT_UFSTYPE_UFS2: |
697 | UFSD("ufstype=ufs2\n"); | 698 | UFSD("ufstype=ufs2\n"); |
698 | super_block_offset=SBLOCK_UFS2; | 699 | super_block_offset=SBLOCK_UFS2; |
699 | uspi->s_fsize = block_size = 512; | 700 | uspi->s_fsize = block_size = 512; |
700 | uspi->s_fmask = ~(512 - 1); | 701 | uspi->s_fmask = ~(512 - 1); |
701 | uspi->s_fshift = 9; | 702 | uspi->s_fshift = 9; |
702 | uspi->s_sbsize = super_block_size = 1536; | 703 | uspi->s_sbsize = super_block_size = 1536; |
703 | uspi->s_sbbase = 0; | 704 | uspi->s_sbbase = 0; |
704 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 705 | flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
705 | break; | 706 | break; |
706 | 707 | ||
707 | case UFS_MOUNT_UFSTYPE_SUN: | 708 | case UFS_MOUNT_UFSTYPE_SUN: |
708 | UFSD("ufstype=sun\n"); | 709 | UFSD("ufstype=sun\n"); |
709 | uspi->s_fsize = block_size = 1024; | 710 | uspi->s_fsize = block_size = 1024; |
710 | uspi->s_fmask = ~(1024 - 1); | 711 | uspi->s_fmask = ~(1024 - 1); |
711 | uspi->s_fshift = 10; | 712 | uspi->s_fshift = 10; |
712 | uspi->s_sbsize = super_block_size = 2048; | 713 | uspi->s_sbsize = super_block_size = 2048; |
713 | uspi->s_sbbase = 0; | 714 | uspi->s_sbbase = 0; |
714 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ | 715 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ |
715 | flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN; | 716 | flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN; |
716 | break; | 717 | break; |
717 | 718 | ||
718 | case UFS_MOUNT_UFSTYPE_SUNOS: | 719 | case UFS_MOUNT_UFSTYPE_SUNOS: |
719 | UFSD(("ufstype=sunos\n")) | 720 | UFSD(("ufstype=sunos\n")) |
720 | uspi->s_fsize = block_size = 1024; | 721 | uspi->s_fsize = block_size = 1024; |
721 | uspi->s_fmask = ~(1024 - 1); | 722 | uspi->s_fmask = ~(1024 - 1); |
722 | uspi->s_fshift = 10; | 723 | uspi->s_fshift = 10; |
723 | uspi->s_sbsize = 2048; | 724 | uspi->s_sbsize = 2048; |
724 | super_block_size = 2048; | 725 | super_block_size = 2048; |
725 | uspi->s_sbbase = 0; | 726 | uspi->s_sbbase = 0; |
726 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ | 727 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ |
727 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN; | 728 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_SUNOS | UFS_CG_SUN; |
728 | break; | 729 | break; |
729 | 730 | ||
730 | case UFS_MOUNT_UFSTYPE_SUNx86: | 731 | case UFS_MOUNT_UFSTYPE_SUNx86: |
731 | UFSD("ufstype=sunx86\n"); | 732 | UFSD("ufstype=sunx86\n"); |
732 | uspi->s_fsize = block_size = 1024; | 733 | uspi->s_fsize = block_size = 1024; |
733 | uspi->s_fmask = ~(1024 - 1); | 734 | uspi->s_fmask = ~(1024 - 1); |
734 | uspi->s_fshift = 10; | 735 | uspi->s_fshift = 10; |
735 | uspi->s_sbsize = super_block_size = 2048; | 736 | uspi->s_sbsize = super_block_size = 2048; |
736 | uspi->s_sbbase = 0; | 737 | uspi->s_sbbase = 0; |
737 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ | 738 | uspi->s_maxsymlinklen = 0; /* Not supported on disk */ |
738 | flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN; | 739 | flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN; |
739 | break; | 740 | break; |
740 | 741 | ||
741 | case UFS_MOUNT_UFSTYPE_OLD: | 742 | case UFS_MOUNT_UFSTYPE_OLD: |
742 | UFSD("ufstype=old\n"); | 743 | UFSD("ufstype=old\n"); |
743 | uspi->s_fsize = block_size = 1024; | 744 | uspi->s_fsize = block_size = 1024; |
744 | uspi->s_fmask = ~(1024 - 1); | 745 | uspi->s_fmask = ~(1024 - 1); |
745 | uspi->s_fshift = 10; | 746 | uspi->s_fshift = 10; |
746 | uspi->s_sbsize = super_block_size = 2048; | 747 | uspi->s_sbsize = super_block_size = 2048; |
747 | uspi->s_sbbase = 0; | 748 | uspi->s_sbbase = 0; |
748 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 749 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
749 | if (!(sb->s_flags & MS_RDONLY)) { | 750 | if (!(sb->s_flags & MS_RDONLY)) { |
750 | if (!silent) | 751 | if (!silent) |
751 | printk(KERN_INFO "ufstype=old is supported read-only\n"); | 752 | printk(KERN_INFO "ufstype=old is supported read-only\n"); |
752 | sb->s_flags |= MS_RDONLY; | 753 | sb->s_flags |= MS_RDONLY; |
753 | } | 754 | } |
754 | break; | 755 | break; |
755 | 756 | ||
756 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: | 757 | case UFS_MOUNT_UFSTYPE_NEXTSTEP: |
757 | /*TODO: check may be we need set special dir block size?*/ | 758 | /*TODO: check may be we need set special dir block size?*/ |
758 | UFSD("ufstype=nextstep\n"); | 759 | UFSD("ufstype=nextstep\n"); |
759 | uspi->s_fsize = block_size = 1024; | 760 | uspi->s_fsize = block_size = 1024; |
760 | uspi->s_fmask = ~(1024 - 1); | 761 | uspi->s_fmask = ~(1024 - 1); |
761 | uspi->s_fshift = 10; | 762 | uspi->s_fshift = 10; |
762 | uspi->s_sbsize = super_block_size = 2048; | 763 | uspi->s_sbsize = super_block_size = 2048; |
763 | uspi->s_sbbase = 0; | 764 | uspi->s_sbbase = 0; |
764 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 765 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
765 | if (!(sb->s_flags & MS_RDONLY)) { | 766 | if (!(sb->s_flags & MS_RDONLY)) { |
766 | if (!silent) | 767 | if (!silent) |
767 | printk(KERN_INFO "ufstype=nextstep is supported read-only\n"); | 768 | printk(KERN_INFO "ufstype=nextstep is supported read-only\n"); |
768 | sb->s_flags |= MS_RDONLY; | 769 | sb->s_flags |= MS_RDONLY; |
769 | } | 770 | } |
770 | break; | 771 | break; |
771 | 772 | ||
772 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: | 773 | case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: |
773 | /*TODO: check may be we need set special dir block size?*/ | 774 | /*TODO: check may be we need set special dir block size?*/ |
774 | UFSD("ufstype=nextstep-cd\n"); | 775 | UFSD("ufstype=nextstep-cd\n"); |
775 | uspi->s_fsize = block_size = 2048; | 776 | uspi->s_fsize = block_size = 2048; |
776 | uspi->s_fmask = ~(2048 - 1); | 777 | uspi->s_fmask = ~(2048 - 1); |
777 | uspi->s_fshift = 11; | 778 | uspi->s_fshift = 11; |
778 | uspi->s_sbsize = super_block_size = 2048; | 779 | uspi->s_sbsize = super_block_size = 2048; |
779 | uspi->s_sbbase = 0; | 780 | uspi->s_sbbase = 0; |
780 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 781 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
781 | if (!(sb->s_flags & MS_RDONLY)) { | 782 | if (!(sb->s_flags & MS_RDONLY)) { |
782 | if (!silent) | 783 | if (!silent) |
783 | printk(KERN_INFO "ufstype=nextstep-cd is supported read-only\n"); | 784 | printk(KERN_INFO "ufstype=nextstep-cd is supported read-only\n"); |
784 | sb->s_flags |= MS_RDONLY; | 785 | sb->s_flags |= MS_RDONLY; |
785 | } | 786 | } |
786 | break; | 787 | break; |
787 | 788 | ||
788 | case UFS_MOUNT_UFSTYPE_OPENSTEP: | 789 | case UFS_MOUNT_UFSTYPE_OPENSTEP: |
789 | UFSD("ufstype=openstep\n"); | 790 | UFSD("ufstype=openstep\n"); |
790 | uspi->s_fsize = block_size = 1024; | 791 | uspi->s_fsize = block_size = 1024; |
791 | uspi->s_fmask = ~(1024 - 1); | 792 | uspi->s_fmask = ~(1024 - 1); |
792 | uspi->s_fshift = 10; | 793 | uspi->s_fshift = 10; |
793 | uspi->s_sbsize = super_block_size = 2048; | 794 | uspi->s_sbsize = super_block_size = 2048; |
794 | uspi->s_sbbase = 0; | 795 | uspi->s_sbbase = 0; |
795 | uspi->s_dirblksize = 1024; | 796 | uspi->s_dirblksize = 1024; |
796 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 797 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
797 | if (!(sb->s_flags & MS_RDONLY)) { | 798 | if (!(sb->s_flags & MS_RDONLY)) { |
798 | if (!silent) | 799 | if (!silent) |
799 | printk(KERN_INFO "ufstype=openstep is supported read-only\n"); | 800 | printk(KERN_INFO "ufstype=openstep is supported read-only\n"); |
800 | sb->s_flags |= MS_RDONLY; | 801 | sb->s_flags |= MS_RDONLY; |
801 | } | 802 | } |
802 | break; | 803 | break; |
803 | 804 | ||
804 | case UFS_MOUNT_UFSTYPE_HP: | 805 | case UFS_MOUNT_UFSTYPE_HP: |
805 | UFSD("ufstype=hp\n"); | 806 | UFSD("ufstype=hp\n"); |
806 | uspi->s_fsize = block_size = 1024; | 807 | uspi->s_fsize = block_size = 1024; |
807 | uspi->s_fmask = ~(1024 - 1); | 808 | uspi->s_fmask = ~(1024 - 1); |
808 | uspi->s_fshift = 10; | 809 | uspi->s_fshift = 10; |
809 | uspi->s_sbsize = super_block_size = 2048; | 810 | uspi->s_sbsize = super_block_size = 2048; |
810 | uspi->s_sbbase = 0; | 811 | uspi->s_sbbase = 0; |
811 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 812 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
812 | if (!(sb->s_flags & MS_RDONLY)) { | 813 | if (!(sb->s_flags & MS_RDONLY)) { |
813 | if (!silent) | 814 | if (!silent) |
814 | printk(KERN_INFO "ufstype=hp is supported read-only\n"); | 815 | printk(KERN_INFO "ufstype=hp is supported read-only\n"); |
815 | sb->s_flags |= MS_RDONLY; | 816 | sb->s_flags |= MS_RDONLY; |
816 | } | 817 | } |
817 | break; | 818 | break; |
818 | default: | 819 | default: |
819 | if (!silent) | 820 | if (!silent) |
820 | printk("unknown ufstype\n"); | 821 | printk("unknown ufstype\n"); |
821 | goto failed; | 822 | goto failed; |
822 | } | 823 | } |
823 | 824 | ||
824 | again: | 825 | again: |
825 | if (!sb_set_blocksize(sb, block_size)) { | 826 | if (!sb_set_blocksize(sb, block_size)) { |
826 | printk(KERN_ERR "UFS: failed to set blocksize\n"); | 827 | printk(KERN_ERR "UFS: failed to set blocksize\n"); |
827 | goto failed; | 828 | goto failed; |
828 | } | 829 | } |
829 | 830 | ||
830 | /* | 831 | /* |
831 | * read ufs super block from device | 832 | * read ufs super block from device |
832 | */ | 833 | */ |
833 | 834 | ||
834 | ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size); | 835 | ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size); |
835 | 836 | ||
836 | if (!ubh) | 837 | if (!ubh) |
837 | goto failed; | 838 | goto failed; |
838 | 839 | ||
839 | usb1 = ubh_get_usb_first(uspi); | 840 | usb1 = ubh_get_usb_first(uspi); |
840 | usb2 = ubh_get_usb_second(uspi); | 841 | usb2 = ubh_get_usb_second(uspi); |
841 | usb3 = ubh_get_usb_third(uspi); | 842 | usb3 = ubh_get_usb_third(uspi); |
842 | 843 | ||
843 | /* Sort out mod used on SunOS 4.1.3 for fs_state */ | 844 | /* Sort out mod used on SunOS 4.1.3 for fs_state */ |
844 | uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat); | 845 | uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat); |
845 | if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) && | 846 | if (((flags & UFS_ST_MASK) == UFS_ST_SUNOS) && |
846 | (uspi->s_postblformat != UFS_42POSTBLFMT)) { | 847 | (uspi->s_postblformat != UFS_42POSTBLFMT)) { |
847 | flags &= ~UFS_ST_MASK; | 848 | flags &= ~UFS_ST_MASK; |
848 | flags |= UFS_ST_SUN; | 849 | flags |= UFS_ST_SUN; |
849 | } | 850 | } |
850 | 851 | ||
851 | /* | 852 | /* |
852 | * Check ufs magic number | 853 | * Check ufs magic number |
853 | */ | 854 | */ |
854 | sbi->s_bytesex = BYTESEX_LE; | 855 | sbi->s_bytesex = BYTESEX_LE; |
855 | switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { | 856 | switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { |
856 | case UFS_MAGIC: | 857 | case UFS_MAGIC: |
857 | case UFS2_MAGIC: | 858 | case UFS2_MAGIC: |
858 | case UFS_MAGIC_LFN: | 859 | case UFS_MAGIC_LFN: |
859 | case UFS_MAGIC_FEA: | 860 | case UFS_MAGIC_FEA: |
860 | case UFS_MAGIC_4GB: | 861 | case UFS_MAGIC_4GB: |
861 | goto magic_found; | 862 | goto magic_found; |
862 | } | 863 | } |
863 | sbi->s_bytesex = BYTESEX_BE; | 864 | sbi->s_bytesex = BYTESEX_BE; |
864 | switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { | 865 | switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) { |
865 | case UFS_MAGIC: | 866 | case UFS_MAGIC: |
866 | case UFS2_MAGIC: | 867 | case UFS2_MAGIC: |
867 | case UFS_MAGIC_LFN: | 868 | case UFS_MAGIC_LFN: |
868 | case UFS_MAGIC_FEA: | 869 | case UFS_MAGIC_FEA: |
869 | case UFS_MAGIC_4GB: | 870 | case UFS_MAGIC_4GB: |
870 | goto magic_found; | 871 | goto magic_found; |
871 | } | 872 | } |
872 | 873 | ||
873 | if ((((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP) | 874 | if ((((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP) |
874 | || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD) | 875 | || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD) |
875 | || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP)) | 876 | || ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP)) |
876 | && uspi->s_sbbase < 256) { | 877 | && uspi->s_sbbase < 256) { |
877 | ubh_brelse_uspi(uspi); | 878 | ubh_brelse_uspi(uspi); |
878 | ubh = NULL; | 879 | ubh = NULL; |
879 | uspi->s_sbbase += 8; | 880 | uspi->s_sbbase += 8; |
880 | goto again; | 881 | goto again; |
881 | } | 882 | } |
882 | if (!silent) | 883 | if (!silent) |
883 | printk("ufs_read_super: bad magic number\n"); | 884 | printk("ufs_read_super: bad magic number\n"); |
884 | goto failed; | 885 | goto failed; |
885 | 886 | ||
886 | magic_found: | 887 | magic_found: |
887 | /* | 888 | /* |
888 | * Check block and fragment sizes | 889 | * Check block and fragment sizes |
889 | */ | 890 | */ |
890 | uspi->s_bsize = fs32_to_cpu(sb, usb1->fs_bsize); | 891 | uspi->s_bsize = fs32_to_cpu(sb, usb1->fs_bsize); |
891 | uspi->s_fsize = fs32_to_cpu(sb, usb1->fs_fsize); | 892 | uspi->s_fsize = fs32_to_cpu(sb, usb1->fs_fsize); |
892 | uspi->s_sbsize = fs32_to_cpu(sb, usb1->fs_sbsize); | 893 | uspi->s_sbsize = fs32_to_cpu(sb, usb1->fs_sbsize); |
893 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); | 894 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); |
894 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); | 895 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); |
895 | 896 | ||
896 | if (!is_power_of_2(uspi->s_fsize)) { | 897 | if (!is_power_of_2(uspi->s_fsize)) { |
897 | printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n", | 898 | printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n", |
898 | uspi->s_fsize); | 899 | uspi->s_fsize); |
899 | goto failed; | 900 | goto failed; |
900 | } | 901 | } |
901 | if (uspi->s_fsize < 512) { | 902 | if (uspi->s_fsize < 512) { |
902 | printk(KERN_ERR "ufs_read_super: fragment size %u is too small\n", | 903 | printk(KERN_ERR "ufs_read_super: fragment size %u is too small\n", |
903 | uspi->s_fsize); | 904 | uspi->s_fsize); |
904 | goto failed; | 905 | goto failed; |
905 | } | 906 | } |
906 | if (uspi->s_fsize > 4096) { | 907 | if (uspi->s_fsize > 4096) { |
907 | printk(KERN_ERR "ufs_read_super: fragment size %u is too large\n", | 908 | printk(KERN_ERR "ufs_read_super: fragment size %u is too large\n", |
908 | uspi->s_fsize); | 909 | uspi->s_fsize); |
909 | goto failed; | 910 | goto failed; |
910 | } | 911 | } |
911 | if (!is_power_of_2(uspi->s_bsize)) { | 912 | if (!is_power_of_2(uspi->s_bsize)) { |
912 | printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n", | 913 | printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n", |
913 | uspi->s_bsize); | 914 | uspi->s_bsize); |
914 | goto failed; | 915 | goto failed; |
915 | } | 916 | } |
916 | if (uspi->s_bsize < 4096) { | 917 | if (uspi->s_bsize < 4096) { |
917 | printk(KERN_ERR "ufs_read_super: block size %u is too small\n", | 918 | printk(KERN_ERR "ufs_read_super: block size %u is too small\n", |
918 | uspi->s_bsize); | 919 | uspi->s_bsize); |
919 | goto failed; | 920 | goto failed; |
920 | } | 921 | } |
921 | if (uspi->s_bsize / uspi->s_fsize > 8) { | 922 | if (uspi->s_bsize / uspi->s_fsize > 8) { |
922 | printk(KERN_ERR "ufs_read_super: too many fragments per block (%u)\n", | 923 | printk(KERN_ERR "ufs_read_super: too many fragments per block (%u)\n", |
923 | uspi->s_bsize / uspi->s_fsize); | 924 | uspi->s_bsize / uspi->s_fsize); |
924 | goto failed; | 925 | goto failed; |
925 | } | 926 | } |
926 | if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { | 927 | if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { |
927 | ubh_brelse_uspi(uspi); | 928 | ubh_brelse_uspi(uspi); |
928 | ubh = NULL; | 929 | ubh = NULL; |
929 | block_size = uspi->s_fsize; | 930 | block_size = uspi->s_fsize; |
930 | super_block_size = uspi->s_sbsize; | 931 | super_block_size = uspi->s_sbsize; |
931 | UFSD("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size); | 932 | UFSD("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size); |
932 | goto again; | 933 | goto again; |
933 | } | 934 | } |
934 | 935 | ||
935 | sbi->s_flags = flags;/*after that line some functions use s_flags*/ | 936 | sbi->s_flags = flags;/*after that line some functions use s_flags*/ |
936 | ufs_print_super_stuff(sb, usb1, usb2, usb3); | 937 | ufs_print_super_stuff(sb, usb1, usb2, usb3); |
937 | 938 | ||
938 | /* | 939 | /* |
939 | * Check, if file system was correctly unmounted. | 940 | * Check, if file system was correctly unmounted. |
940 | * If not, make it read only. | 941 | * If not, make it read only. |
941 | */ | 942 | */ |
942 | if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || | 943 | if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) || |
943 | ((flags & UFS_ST_MASK) == UFS_ST_OLD) || | 944 | ((flags & UFS_ST_MASK) == UFS_ST_OLD) || |
944 | (((flags & UFS_ST_MASK) == UFS_ST_SUN || | 945 | (((flags & UFS_ST_MASK) == UFS_ST_SUN || |
945 | (flags & UFS_ST_MASK) == UFS_ST_SUNOS || | 946 | (flags & UFS_ST_MASK) == UFS_ST_SUNOS || |
946 | (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && | 947 | (flags & UFS_ST_MASK) == UFS_ST_SUNx86) && |
947 | (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) { | 948 | (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) { |
948 | switch(usb1->fs_clean) { | 949 | switch(usb1->fs_clean) { |
949 | case UFS_FSCLEAN: | 950 | case UFS_FSCLEAN: |
950 | UFSD("fs is clean\n"); | 951 | UFSD("fs is clean\n"); |
951 | break; | 952 | break; |
952 | case UFS_FSSTABLE: | 953 | case UFS_FSSTABLE: |
953 | UFSD("fs is stable\n"); | 954 | UFSD("fs is stable\n"); |
954 | break; | 955 | break; |
955 | case UFS_FSOSF1: | 956 | case UFS_FSOSF1: |
956 | UFSD("fs is DEC OSF/1\n"); | 957 | UFSD("fs is DEC OSF/1\n"); |
957 | break; | 958 | break; |
958 | case UFS_FSACTIVE: | 959 | case UFS_FSACTIVE: |
959 | printk("ufs_read_super: fs is active\n"); | 960 | printk("ufs_read_super: fs is active\n"); |
960 | sb->s_flags |= MS_RDONLY; | 961 | sb->s_flags |= MS_RDONLY; |
961 | break; | 962 | break; |
962 | case UFS_FSBAD: | 963 | case UFS_FSBAD: |
963 | printk("ufs_read_super: fs is bad\n"); | 964 | printk("ufs_read_super: fs is bad\n"); |
964 | sb->s_flags |= MS_RDONLY; | 965 | sb->s_flags |= MS_RDONLY; |
965 | break; | 966 | break; |
966 | default: | 967 | default: |
967 | printk("ufs_read_super: can't grok fs_clean 0x%x\n", usb1->fs_clean); | 968 | printk("ufs_read_super: can't grok fs_clean 0x%x\n", usb1->fs_clean); |
968 | sb->s_flags |= MS_RDONLY; | 969 | sb->s_flags |= MS_RDONLY; |
969 | break; | 970 | break; |
970 | } | 971 | } |
971 | } else { | 972 | } else { |
972 | printk("ufs_read_super: fs needs fsck\n"); | 973 | printk("ufs_read_super: fs needs fsck\n"); |
973 | sb->s_flags |= MS_RDONLY; | 974 | sb->s_flags |= MS_RDONLY; |
974 | } | 975 | } |
975 | 976 | ||
976 | /* | 977 | /* |
977 | * Read ufs_super_block into internal data structures | 978 | * Read ufs_super_block into internal data structures |
978 | */ | 979 | */ |
979 | sb->s_op = &ufs_super_ops; | 980 | sb->s_op = &ufs_super_ops; |
980 | sb->dq_op = NULL; /***/ | 981 | sb->dq_op = NULL; /***/ |
981 | sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic); | 982 | sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic); |
982 | 983 | ||
983 | uspi->s_sblkno = fs32_to_cpu(sb, usb1->fs_sblkno); | 984 | uspi->s_sblkno = fs32_to_cpu(sb, usb1->fs_sblkno); |
984 | uspi->s_cblkno = fs32_to_cpu(sb, usb1->fs_cblkno); | 985 | uspi->s_cblkno = fs32_to_cpu(sb, usb1->fs_cblkno); |
985 | uspi->s_iblkno = fs32_to_cpu(sb, usb1->fs_iblkno); | 986 | uspi->s_iblkno = fs32_to_cpu(sb, usb1->fs_iblkno); |
986 | uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno); | 987 | uspi->s_dblkno = fs32_to_cpu(sb, usb1->fs_dblkno); |
987 | uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset); | 988 | uspi->s_cgoffset = fs32_to_cpu(sb, usb1->fs_cgoffset); |
988 | uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask); | 989 | uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask); |
989 | 990 | ||
990 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 991 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { |
991 | uspi->s_u2_size = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size); | 992 | uspi->s_u2_size = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size); |
992 | uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); | 993 | uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); |
993 | } else { | 994 | } else { |
994 | uspi->s_size = fs32_to_cpu(sb, usb1->fs_size); | 995 | uspi->s_size = fs32_to_cpu(sb, usb1->fs_size); |
995 | uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize); | 996 | uspi->s_dsize = fs32_to_cpu(sb, usb1->fs_dsize); |
996 | } | 997 | } |
997 | 998 | ||
998 | uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg); | 999 | uspi->s_ncg = fs32_to_cpu(sb, usb1->fs_ncg); |
999 | /* s_bsize already set */ | 1000 | /* s_bsize already set */ |
1000 | /* s_fsize already set */ | 1001 | /* s_fsize already set */ |
1001 | uspi->s_fpb = fs32_to_cpu(sb, usb1->fs_frag); | 1002 | uspi->s_fpb = fs32_to_cpu(sb, usb1->fs_frag); |
1002 | uspi->s_minfree = fs32_to_cpu(sb, usb1->fs_minfree); | 1003 | uspi->s_minfree = fs32_to_cpu(sb, usb1->fs_minfree); |
1003 | uspi->s_bmask = fs32_to_cpu(sb, usb1->fs_bmask); | 1004 | uspi->s_bmask = fs32_to_cpu(sb, usb1->fs_bmask); |
1004 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); | 1005 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); |
1005 | uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift); | 1006 | uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift); |
1006 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); | 1007 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); |
1007 | UFSD("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift, | 1008 | UFSD("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift, |
1008 | uspi->s_fshift); | 1009 | uspi->s_fshift); |
1009 | uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift); | 1010 | uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift); |
1010 | uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb); | 1011 | uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb); |
1011 | /* s_sbsize already set */ | 1012 | /* s_sbsize already set */ |
1012 | uspi->s_csmask = fs32_to_cpu(sb, usb1->fs_csmask); | 1013 | uspi->s_csmask = fs32_to_cpu(sb, usb1->fs_csmask); |
1013 | uspi->s_csshift = fs32_to_cpu(sb, usb1->fs_csshift); | 1014 | uspi->s_csshift = fs32_to_cpu(sb, usb1->fs_csshift); |
1014 | uspi->s_nindir = fs32_to_cpu(sb, usb1->fs_nindir); | 1015 | uspi->s_nindir = fs32_to_cpu(sb, usb1->fs_nindir); |
1015 | uspi->s_inopb = fs32_to_cpu(sb, usb1->fs_inopb); | 1016 | uspi->s_inopb = fs32_to_cpu(sb, usb1->fs_inopb); |
1016 | uspi->s_nspf = fs32_to_cpu(sb, usb1->fs_nspf); | 1017 | uspi->s_nspf = fs32_to_cpu(sb, usb1->fs_nspf); |
1017 | uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); | 1018 | uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3); |
1018 | uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); | 1019 | uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave); |
1019 | uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); | 1020 | uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew); |
1020 | 1021 | ||
1021 | if (uspi->fs_magic == UFS2_MAGIC) | 1022 | if (uspi->fs_magic == UFS2_MAGIC) |
1022 | uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr); | 1023 | uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr); |
1023 | else | 1024 | else |
1024 | uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); | 1025 | uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); |
1025 | 1026 | ||
1026 | uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); | 1027 | uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); |
1027 | uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); | 1028 | uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); |
1028 | uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); | 1029 | uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); |
1029 | uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect); | 1030 | uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect); |
1030 | uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc); | 1031 | uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc); |
1031 | uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg); | 1032 | uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg); |
1032 | uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg); | 1033 | uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg); |
1033 | uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_un.fs_u1.fs_cpc); | 1034 | uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_un.fs_u1.fs_cpc); |
1034 | uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize); | 1035 | uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize); |
1035 | uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3); | 1036 | uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3); |
1036 | uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3); | 1037 | uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3); |
1037 | uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos); | 1038 | uspi->s_nrpos = fs32_to_cpu(sb, usb3->fs_nrpos); |
1038 | uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff); | 1039 | uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff); |
1039 | uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff); | 1040 | uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff); |
1040 | 1041 | ||
1041 | /* | 1042 | /* |
1042 | * Compute another frequently used values | 1043 | * Compute another frequently used values |
1043 | */ | 1044 | */ |
1044 | uspi->s_fpbmask = uspi->s_fpb - 1; | 1045 | uspi->s_fpbmask = uspi->s_fpb - 1; |
1045 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) | 1046 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) |
1046 | uspi->s_apbshift = uspi->s_bshift - 3; | 1047 | uspi->s_apbshift = uspi->s_bshift - 3; |
1047 | else | 1048 | else |
1048 | uspi->s_apbshift = uspi->s_bshift - 2; | 1049 | uspi->s_apbshift = uspi->s_bshift - 2; |
1049 | 1050 | ||
1050 | uspi->s_2apbshift = uspi->s_apbshift * 2; | 1051 | uspi->s_2apbshift = uspi->s_apbshift * 2; |
1051 | uspi->s_3apbshift = uspi->s_apbshift * 3; | 1052 | uspi->s_3apbshift = uspi->s_apbshift * 3; |
1052 | uspi->s_apb = 1 << uspi->s_apbshift; | 1053 | uspi->s_apb = 1 << uspi->s_apbshift; |
1053 | uspi->s_2apb = 1 << uspi->s_2apbshift; | 1054 | uspi->s_2apb = 1 << uspi->s_2apbshift; |
1054 | uspi->s_3apb = 1 << uspi->s_3apbshift; | 1055 | uspi->s_3apb = 1 << uspi->s_3apbshift; |
1055 | uspi->s_apbmask = uspi->s_apb - 1; | 1056 | uspi->s_apbmask = uspi->s_apb - 1; |
1056 | uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; | 1057 | uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; |
1057 | uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; | 1058 | uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; |
1058 | uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; | 1059 | uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; |
1059 | uspi->s_bpf = uspi->s_fsize << 3; | 1060 | uspi->s_bpf = uspi->s_fsize << 3; |
1060 | uspi->s_bpfshift = uspi->s_fshift + 3; | 1061 | uspi->s_bpfshift = uspi->s_fshift + 3; |
1061 | uspi->s_bpfmask = uspi->s_bpf - 1; | 1062 | uspi->s_bpfmask = uspi->s_bpf - 1; |
1062 | if ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == | 1063 | if ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) == |
1063 | UFS_MOUNT_UFSTYPE_44BSD) | 1064 | UFS_MOUNT_UFSTYPE_44BSD) |
1064 | uspi->s_maxsymlinklen = | 1065 | uspi->s_maxsymlinklen = |
1065 | fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen); | 1066 | fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen); |
1066 | 1067 | ||
1067 | inode = iget(sb, UFS_ROOTINO); | 1068 | inode = iget(sb, UFS_ROOTINO); |
1068 | if (!inode || is_bad_inode(inode)) | 1069 | if (!inode || is_bad_inode(inode)) |
1069 | goto failed; | 1070 | goto failed; |
1070 | sb->s_root = d_alloc_root(inode); | 1071 | sb->s_root = d_alloc_root(inode); |
1071 | if (!sb->s_root) | 1072 | if (!sb->s_root) |
1072 | goto dalloc_failed; | 1073 | goto dalloc_failed; |
1073 | 1074 | ||
1074 | ufs_setup_cstotal(sb); | 1075 | ufs_setup_cstotal(sb); |
1075 | /* | 1076 | /* |
1076 | * Read cylinder group structures | 1077 | * Read cylinder group structures |
1077 | */ | 1078 | */ |
1078 | if (!(sb->s_flags & MS_RDONLY)) | 1079 | if (!(sb->s_flags & MS_RDONLY)) |
1079 | if (!ufs_read_cylinder_structures(sb)) | 1080 | if (!ufs_read_cylinder_structures(sb)) |
1080 | goto failed; | 1081 | goto failed; |
1081 | 1082 | ||
1082 | UFSD("EXIT\n"); | 1083 | UFSD("EXIT\n"); |
1083 | return 0; | 1084 | return 0; |
1084 | 1085 | ||
1085 | dalloc_failed: | 1086 | dalloc_failed: |
1086 | iput(inode); | 1087 | iput(inode); |
1087 | failed: | 1088 | failed: |
1088 | if (ubh) | 1089 | if (ubh) |
1089 | ubh_brelse_uspi (uspi); | 1090 | ubh_brelse_uspi (uspi); |
1090 | kfree (uspi); | 1091 | kfree (uspi); |
1091 | kfree(sbi); | 1092 | kfree(sbi); |
1092 | sb->s_fs_info = NULL; | 1093 | sb->s_fs_info = NULL; |
1093 | UFSD("EXIT (FAILED)\n"); | 1094 | UFSD("EXIT (FAILED)\n"); |
1094 | return -EINVAL; | 1095 | return -EINVAL; |
1095 | 1096 | ||
1096 | failed_nomem: | 1097 | failed_nomem: |
1097 | UFSD("EXIT (NOMEM)\n"); | 1098 | UFSD("EXIT (NOMEM)\n"); |
1098 | return -ENOMEM; | 1099 | return -ENOMEM; |
1099 | } | 1100 | } |
1100 | 1101 | ||
1101 | static void ufs_write_super(struct super_block *sb) | 1102 | static void ufs_write_super(struct super_block *sb) |
1102 | { | 1103 | { |
1103 | struct ufs_sb_private_info * uspi; | 1104 | struct ufs_sb_private_info * uspi; |
1104 | struct ufs_super_block_first * usb1; | 1105 | struct ufs_super_block_first * usb1; |
1105 | struct ufs_super_block_third * usb3; | 1106 | struct ufs_super_block_third * usb3; |
1106 | unsigned flags; | 1107 | unsigned flags; |
1107 | 1108 | ||
1108 | lock_kernel(); | 1109 | lock_kernel(); |
1109 | UFSD("ENTER\n"); | 1110 | UFSD("ENTER\n"); |
1110 | flags = UFS_SB(sb)->s_flags; | 1111 | flags = UFS_SB(sb)->s_flags; |
1111 | uspi = UFS_SB(sb)->s_uspi; | 1112 | uspi = UFS_SB(sb)->s_uspi; |
1112 | usb1 = ubh_get_usb_first(uspi); | 1113 | usb1 = ubh_get_usb_first(uspi); |
1113 | usb3 = ubh_get_usb_third(uspi); | 1114 | usb3 = ubh_get_usb_third(uspi); |
1114 | 1115 | ||
1115 | if (!(sb->s_flags & MS_RDONLY)) { | 1116 | if (!(sb->s_flags & MS_RDONLY)) { |
1116 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | 1117 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); |
1117 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN | 1118 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN |
1118 | || (flags & UFS_ST_MASK) == UFS_ST_SUNOS | 1119 | || (flags & UFS_ST_MASK) == UFS_ST_SUNOS |
1119 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 1120 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
1120 | ufs_set_fs_state(sb, usb1, usb3, | 1121 | ufs_set_fs_state(sb, usb1, usb3, |
1121 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | 1122 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); |
1122 | ufs_put_cstotal(sb); | 1123 | ufs_put_cstotal(sb); |
1123 | } | 1124 | } |
1124 | sb->s_dirt = 0; | 1125 | sb->s_dirt = 0; |
1125 | UFSD("EXIT\n"); | 1126 | UFSD("EXIT\n"); |
1126 | unlock_kernel(); | 1127 | unlock_kernel(); |
1127 | } | 1128 | } |
1128 | 1129 | ||
1129 | static void ufs_put_super(struct super_block *sb) | 1130 | static void ufs_put_super(struct super_block *sb) |
1130 | { | 1131 | { |
1131 | struct ufs_sb_info * sbi = UFS_SB(sb); | 1132 | struct ufs_sb_info * sbi = UFS_SB(sb); |
1132 | 1133 | ||
1133 | UFSD("ENTER\n"); | 1134 | UFSD("ENTER\n"); |
1134 | 1135 | ||
1135 | if (!(sb->s_flags & MS_RDONLY)) | 1136 | if (!(sb->s_flags & MS_RDONLY)) |
1136 | ufs_put_super_internal(sb); | 1137 | ufs_put_super_internal(sb); |
1137 | 1138 | ||
1138 | ubh_brelse_uspi (sbi->s_uspi); | 1139 | ubh_brelse_uspi (sbi->s_uspi); |
1139 | kfree (sbi->s_uspi); | 1140 | kfree (sbi->s_uspi); |
1140 | kfree (sbi); | 1141 | kfree (sbi); |
1141 | sb->s_fs_info = NULL; | 1142 | sb->s_fs_info = NULL; |
1142 | UFSD("EXIT\n"); | 1143 | UFSD("EXIT\n"); |
1143 | return; | 1144 | return; |
1144 | } | 1145 | } |
1145 | 1146 | ||
1146 | 1147 | ||
1147 | static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | 1148 | static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) |
1148 | { | 1149 | { |
1149 | struct ufs_sb_private_info * uspi; | 1150 | struct ufs_sb_private_info * uspi; |
1150 | struct ufs_super_block_first * usb1; | 1151 | struct ufs_super_block_first * usb1; |
1151 | struct ufs_super_block_third * usb3; | 1152 | struct ufs_super_block_third * usb3; |
1152 | unsigned new_mount_opt, ufstype; | 1153 | unsigned new_mount_opt, ufstype; |
1153 | unsigned flags; | 1154 | unsigned flags; |
1154 | 1155 | ||
1155 | uspi = UFS_SB(sb)->s_uspi; | 1156 | uspi = UFS_SB(sb)->s_uspi; |
1156 | flags = UFS_SB(sb)->s_flags; | 1157 | flags = UFS_SB(sb)->s_flags; |
1157 | usb1 = ubh_get_usb_first(uspi); | 1158 | usb1 = ubh_get_usb_first(uspi); |
1158 | usb3 = ubh_get_usb_third(uspi); | 1159 | usb3 = ubh_get_usb_third(uspi); |
1159 | 1160 | ||
1160 | /* | 1161 | /* |
1161 | * Allow the "check" option to be passed as a remount option. | 1162 | * Allow the "check" option to be passed as a remount option. |
1162 | * It is not possible to change ufstype option during remount | 1163 | * It is not possible to change ufstype option during remount |
1163 | */ | 1164 | */ |
1164 | ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; | 1165 | ufstype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; |
1165 | new_mount_opt = 0; | 1166 | new_mount_opt = 0; |
1166 | ufs_set_opt (new_mount_opt, ONERROR_LOCK); | 1167 | ufs_set_opt (new_mount_opt, ONERROR_LOCK); |
1167 | if (!ufs_parse_options (data, &new_mount_opt)) | 1168 | if (!ufs_parse_options (data, &new_mount_opt)) |
1168 | return -EINVAL; | 1169 | return -EINVAL; |
1169 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { | 1170 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { |
1170 | new_mount_opt |= ufstype; | 1171 | new_mount_opt |= ufstype; |
1171 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { | 1172 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { |
1172 | printk("ufstype can't be changed during remount\n"); | 1173 | printk("ufstype can't be changed during remount\n"); |
1173 | return -EINVAL; | 1174 | return -EINVAL; |
1174 | } | 1175 | } |
1175 | 1176 | ||
1176 | if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { | 1177 | if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
1177 | UFS_SB(sb)->s_mount_opt = new_mount_opt; | 1178 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
1178 | return 0; | 1179 | return 0; |
1179 | } | 1180 | } |
1180 | 1181 | ||
1181 | /* | 1182 | /* |
1182 | * fs was mouted as rw, remounting ro | 1183 | * fs was mouted as rw, remounting ro |
1183 | */ | 1184 | */ |
1184 | if (*mount_flags & MS_RDONLY) { | 1185 | if (*mount_flags & MS_RDONLY) { |
1185 | ufs_put_super_internal(sb); | 1186 | ufs_put_super_internal(sb); |
1186 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | 1187 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); |
1187 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN | 1188 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN |
1188 | || (flags & UFS_ST_MASK) == UFS_ST_SUNOS | 1189 | || (flags & UFS_ST_MASK) == UFS_ST_SUNOS |
1189 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 1190 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
1190 | ufs_set_fs_state(sb, usb1, usb3, | 1191 | ufs_set_fs_state(sb, usb1, usb3, |
1191 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | 1192 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); |
1192 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 1193 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
1193 | sb->s_dirt = 0; | 1194 | sb->s_dirt = 0; |
1194 | sb->s_flags |= MS_RDONLY; | 1195 | sb->s_flags |= MS_RDONLY; |
1195 | } else { | 1196 | } else { |
1196 | /* | 1197 | /* |
1197 | * fs was mounted as ro, remounting rw | 1198 | * fs was mounted as ro, remounting rw |
1198 | */ | 1199 | */ |
1199 | #ifndef CONFIG_UFS_FS_WRITE | 1200 | #ifndef CONFIG_UFS_FS_WRITE |
1200 | printk("ufs was compiled with read-only support, " | 1201 | printk("ufs was compiled with read-only support, " |
1201 | "can't be mounted as read-write\n"); | 1202 | "can't be mounted as read-write\n"); |
1202 | return -EINVAL; | 1203 | return -EINVAL; |
1203 | #else | 1204 | #else |
1204 | if (ufstype != UFS_MOUNT_UFSTYPE_SUN && | 1205 | if (ufstype != UFS_MOUNT_UFSTYPE_SUN && |
1205 | ufstype != UFS_MOUNT_UFSTYPE_SUNOS && | 1206 | ufstype != UFS_MOUNT_UFSTYPE_SUNOS && |
1206 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && | 1207 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && |
1207 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && | 1208 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && |
1208 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { | 1209 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { |
1209 | printk("this ufstype is read-only supported\n"); | 1210 | printk("this ufstype is read-only supported\n"); |
1210 | return -EINVAL; | 1211 | return -EINVAL; |
1211 | } | 1212 | } |
1212 | if (!ufs_read_cylinder_structures(sb)) { | 1213 | if (!ufs_read_cylinder_structures(sb)) { |
1213 | printk("failed during remounting\n"); | 1214 | printk("failed during remounting\n"); |
1214 | return -EPERM; | 1215 | return -EPERM; |
1215 | } | 1216 | } |
1216 | sb->s_flags &= ~MS_RDONLY; | 1217 | sb->s_flags &= ~MS_RDONLY; |
1217 | #endif | 1218 | #endif |
1218 | } | 1219 | } |
1219 | UFS_SB(sb)->s_mount_opt = new_mount_opt; | 1220 | UFS_SB(sb)->s_mount_opt = new_mount_opt; |
1220 | return 0; | 1221 | return 0; |
1221 | } | 1222 | } |
1222 | 1223 | ||
1223 | static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs) | 1224 | static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
1224 | { | 1225 | { |
1225 | struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb); | 1226 | struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb); |
1226 | unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; | 1227 | unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; |
1227 | struct match_token *tp = tokens; | 1228 | struct match_token *tp = tokens; |
1228 | 1229 | ||
1229 | while (tp->token != Opt_onerror_panic && tp->token != mval) | 1230 | while (tp->token != Opt_onerror_panic && tp->token != mval) |
1230 | ++tp; | 1231 | ++tp; |
1231 | BUG_ON(tp->token == Opt_onerror_panic); | 1232 | BUG_ON(tp->token == Opt_onerror_panic); |
1232 | seq_printf(seq, ",%s", tp->pattern); | 1233 | seq_printf(seq, ",%s", tp->pattern); |
1233 | 1234 | ||
1234 | mval = sbi->s_mount_opt & UFS_MOUNT_ONERROR; | 1235 | mval = sbi->s_mount_opt & UFS_MOUNT_ONERROR; |
1235 | while (tp->token != Opt_err && tp->token != mval) | 1236 | while (tp->token != Opt_err && tp->token != mval) |
1236 | ++tp; | 1237 | ++tp; |
1237 | BUG_ON(tp->token == Opt_err); | 1238 | BUG_ON(tp->token == Opt_err); |
1238 | seq_printf(seq, ",%s", tp->pattern); | 1239 | seq_printf(seq, ",%s", tp->pattern); |
1239 | 1240 | ||
1240 | return 0; | 1241 | return 0; |
1241 | } | 1242 | } |
1242 | 1243 | ||
1243 | static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) | 1244 | static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) |
1244 | { | 1245 | { |
1245 | struct super_block *sb = dentry->d_sb; | 1246 | struct super_block *sb = dentry->d_sb; |
1246 | struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi; | 1247 | struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi; |
1247 | unsigned flags = UFS_SB(sb)->s_flags; | 1248 | unsigned flags = UFS_SB(sb)->s_flags; |
1248 | struct ufs_super_block_first *usb1; | 1249 | struct ufs_super_block_first *usb1; |
1249 | struct ufs_super_block_second *usb2; | 1250 | struct ufs_super_block_second *usb2; |
1250 | struct ufs_super_block_third *usb3; | 1251 | struct ufs_super_block_third *usb3; |
1251 | 1252 | ||
1252 | lock_kernel(); | 1253 | lock_kernel(); |
1253 | 1254 | ||
1254 | usb1 = ubh_get_usb_first(uspi); | 1255 | usb1 = ubh_get_usb_first(uspi); |
1255 | usb2 = ubh_get_usb_second(uspi); | 1256 | usb2 = ubh_get_usb_second(uspi); |
1256 | usb3 = ubh_get_usb_third(uspi); | 1257 | usb3 = ubh_get_usb_third(uspi); |
1257 | 1258 | ||
1258 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 1259 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { |
1259 | buf->f_type = UFS2_MAGIC; | 1260 | buf->f_type = UFS2_MAGIC; |
1260 | buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); | 1261 | buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); |
1261 | } else { | 1262 | } else { |
1262 | buf->f_type = UFS_MAGIC; | 1263 | buf->f_type = UFS_MAGIC; |
1263 | buf->f_blocks = uspi->s_dsize; | 1264 | buf->f_blocks = uspi->s_dsize; |
1264 | } | 1265 | } |
1265 | buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) + | 1266 | buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) + |
1266 | uspi->cs_total.cs_nffree; | 1267 | uspi->cs_total.cs_nffree; |
1267 | buf->f_ffree = uspi->cs_total.cs_nifree; | 1268 | buf->f_ffree = uspi->cs_total.cs_nifree; |
1268 | buf->f_bsize = sb->s_blocksize; | 1269 | buf->f_bsize = sb->s_blocksize; |
1269 | buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree)) | 1270 | buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree)) |
1270 | ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; | 1271 | ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; |
1271 | buf->f_files = uspi->s_ncg * uspi->s_ipg; | 1272 | buf->f_files = uspi->s_ncg * uspi->s_ipg; |
1272 | buf->f_namelen = UFS_MAXNAMLEN; | 1273 | buf->f_namelen = UFS_MAXNAMLEN; |
1273 | 1274 | ||
1274 | unlock_kernel(); | 1275 | unlock_kernel(); |
1275 | 1276 | ||
1276 | return 0; | 1277 | return 0; |
1277 | } | 1278 | } |
1278 | 1279 | ||
1279 | static struct kmem_cache * ufs_inode_cachep; | 1280 | static struct kmem_cache * ufs_inode_cachep; |
1280 | 1281 | ||
1281 | static struct inode *ufs_alloc_inode(struct super_block *sb) | 1282 | static struct inode *ufs_alloc_inode(struct super_block *sb) |
1282 | { | 1283 | { |
1283 | struct ufs_inode_info *ei; | 1284 | struct ufs_inode_info *ei; |
1284 | ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL); | 1285 | ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL); |
1285 | if (!ei) | 1286 | if (!ei) |
1286 | return NULL; | 1287 | return NULL; |
1287 | ei->vfs_inode.i_version = 1; | 1288 | ei->vfs_inode.i_version = 1; |
1288 | return &ei->vfs_inode; | 1289 | return &ei->vfs_inode; |
1289 | } | 1290 | } |
1290 | 1291 | ||
1291 | static void ufs_destroy_inode(struct inode *inode) | 1292 | static void ufs_destroy_inode(struct inode *inode) |
1292 | { | 1293 | { |
1293 | kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); | 1294 | kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); |
1294 | } | 1295 | } |
1295 | 1296 | ||
1296 | static void init_once(struct kmem_cache * cachep, void *foo) | 1297 | static void init_once(struct kmem_cache * cachep, void *foo) |
1297 | { | 1298 | { |
1298 | struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; | 1299 | struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; |
1299 | 1300 | ||
1300 | inode_init_once(&ei->vfs_inode); | 1301 | inode_init_once(&ei->vfs_inode); |
1301 | } | 1302 | } |
1302 | 1303 | ||
1303 | static int init_inodecache(void) | 1304 | static int init_inodecache(void) |
1304 | { | 1305 | { |
1305 | ufs_inode_cachep = kmem_cache_create("ufs_inode_cache", | 1306 | ufs_inode_cachep = kmem_cache_create("ufs_inode_cache", |
1306 | sizeof(struct ufs_inode_info), | 1307 | sizeof(struct ufs_inode_info), |
1307 | 0, (SLAB_RECLAIM_ACCOUNT| | 1308 | 0, (SLAB_RECLAIM_ACCOUNT| |
1308 | SLAB_MEM_SPREAD), | 1309 | SLAB_MEM_SPREAD), |
1309 | init_once); | 1310 | init_once); |
1310 | if (ufs_inode_cachep == NULL) | 1311 | if (ufs_inode_cachep == NULL) |
1311 | return -ENOMEM; | 1312 | return -ENOMEM; |
1312 | return 0; | 1313 | return 0; |
1313 | } | 1314 | } |
1314 | 1315 | ||
1315 | static void destroy_inodecache(void) | 1316 | static void destroy_inodecache(void) |
1316 | { | 1317 | { |
1317 | kmem_cache_destroy(ufs_inode_cachep); | 1318 | kmem_cache_destroy(ufs_inode_cachep); |
1318 | } | 1319 | } |
1319 | 1320 | ||
1320 | #ifdef CONFIG_QUOTA | 1321 | #ifdef CONFIG_QUOTA |
1321 | static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t); | 1322 | static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t); |
1322 | static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t); | 1323 | static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t); |
1323 | #endif | 1324 | #endif |
1324 | 1325 | ||
1325 | static const struct super_operations ufs_super_ops = { | 1326 | static const struct super_operations ufs_super_ops = { |
1326 | .alloc_inode = ufs_alloc_inode, | 1327 | .alloc_inode = ufs_alloc_inode, |
1327 | .destroy_inode = ufs_destroy_inode, | 1328 | .destroy_inode = ufs_destroy_inode, |
1328 | .read_inode = ufs_read_inode, | 1329 | .read_inode = ufs_read_inode, |
1329 | .write_inode = ufs_write_inode, | 1330 | .write_inode = ufs_write_inode, |
1330 | .delete_inode = ufs_delete_inode, | 1331 | .delete_inode = ufs_delete_inode, |
1331 | .put_super = ufs_put_super, | 1332 | .put_super = ufs_put_super, |
1332 | .write_super = ufs_write_super, | 1333 | .write_super = ufs_write_super, |
1333 | .statfs = ufs_statfs, | 1334 | .statfs = ufs_statfs, |
1334 | .remount_fs = ufs_remount, | 1335 | .remount_fs = ufs_remount, |
1335 | .show_options = ufs_show_options, | 1336 | .show_options = ufs_show_options, |
1336 | #ifdef CONFIG_QUOTA | 1337 | #ifdef CONFIG_QUOTA |
1337 | .quota_read = ufs_quota_read, | 1338 | .quota_read = ufs_quota_read, |
1338 | .quota_write = ufs_quota_write, | 1339 | .quota_write = ufs_quota_write, |
1339 | #endif | 1340 | #endif |
1340 | }; | 1341 | }; |
1341 | 1342 | ||
1342 | #ifdef CONFIG_QUOTA | 1343 | #ifdef CONFIG_QUOTA |
1343 | 1344 | ||
1344 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 1345 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
1345 | * acquiring the locks... As quota files are never truncated and quota code | 1346 | * acquiring the locks... As quota files are never truncated and quota code |
1346 | * itself serializes the operations (and noone else should touch the files) | 1347 | * itself serializes the operations (and noone else should touch the files) |
1347 | * we don't have to be afraid of races */ | 1348 | * we don't have to be afraid of races */ |
1348 | static ssize_t ufs_quota_read(struct super_block *sb, int type, char *data, | 1349 | static ssize_t ufs_quota_read(struct super_block *sb, int type, char *data, |
1349 | size_t len, loff_t off) | 1350 | size_t len, loff_t off) |
1350 | { | 1351 | { |
1351 | struct inode *inode = sb_dqopt(sb)->files[type]; | 1352 | struct inode *inode = sb_dqopt(sb)->files[type]; |
1352 | sector_t blk = off >> sb->s_blocksize_bits; | 1353 | sector_t blk = off >> sb->s_blocksize_bits; |
1353 | int err = 0; | 1354 | int err = 0; |
1354 | int offset = off & (sb->s_blocksize - 1); | 1355 | int offset = off & (sb->s_blocksize - 1); |
1355 | int tocopy; | 1356 | int tocopy; |
1356 | size_t toread; | 1357 | size_t toread; |
1357 | struct buffer_head *bh; | 1358 | struct buffer_head *bh; |
1358 | loff_t i_size = i_size_read(inode); | 1359 | loff_t i_size = i_size_read(inode); |
1359 | 1360 | ||
1360 | if (off > i_size) | 1361 | if (off > i_size) |
1361 | return 0; | 1362 | return 0; |
1362 | if (off+len > i_size) | 1363 | if (off+len > i_size) |
1363 | len = i_size-off; | 1364 | len = i_size-off; |
1364 | toread = len; | 1365 | toread = len; |
1365 | while (toread > 0) { | 1366 | while (toread > 0) { |
1366 | tocopy = sb->s_blocksize - offset < toread ? | 1367 | tocopy = sb->s_blocksize - offset < toread ? |
1367 | sb->s_blocksize - offset : toread; | 1368 | sb->s_blocksize - offset : toread; |
1368 | 1369 | ||
1369 | bh = ufs_bread(inode, blk, 0, &err); | 1370 | bh = ufs_bread(inode, blk, 0, &err); |
1370 | if (err) | 1371 | if (err) |
1371 | return err; | 1372 | return err; |
1372 | if (!bh) /* A hole? */ | 1373 | if (!bh) /* A hole? */ |
1373 | memset(data, 0, tocopy); | 1374 | memset(data, 0, tocopy); |
1374 | else { | 1375 | else { |
1375 | memcpy(data, bh->b_data+offset, tocopy); | 1376 | memcpy(data, bh->b_data+offset, tocopy); |
1376 | brelse(bh); | 1377 | brelse(bh); |
1377 | } | 1378 | } |
1378 | offset = 0; | 1379 | offset = 0; |
1379 | toread -= tocopy; | 1380 | toread -= tocopy; |
1380 | data += tocopy; | 1381 | data += tocopy; |
1381 | blk++; | 1382 | blk++; |
1382 | } | 1383 | } |
1383 | return len; | 1384 | return len; |
1384 | } | 1385 | } |
1385 | 1386 | ||
1386 | /* Write to quotafile */ | 1387 | /* Write to quotafile */ |
1387 | static ssize_t ufs_quota_write(struct super_block *sb, int type, | 1388 | static ssize_t ufs_quota_write(struct super_block *sb, int type, |
1388 | const char *data, size_t len, loff_t off) | 1389 | const char *data, size_t len, loff_t off) |
1389 | { | 1390 | { |
1390 | struct inode *inode = sb_dqopt(sb)->files[type]; | 1391 | struct inode *inode = sb_dqopt(sb)->files[type]; |
1391 | sector_t blk = off >> sb->s_blocksize_bits; | 1392 | sector_t blk = off >> sb->s_blocksize_bits; |
1392 | int err = 0; | 1393 | int err = 0; |
1393 | int offset = off & (sb->s_blocksize - 1); | 1394 | int offset = off & (sb->s_blocksize - 1); |
1394 | int tocopy; | 1395 | int tocopy; |
1395 | size_t towrite = len; | 1396 | size_t towrite = len; |
1396 | struct buffer_head *bh; | 1397 | struct buffer_head *bh; |
1397 | 1398 | ||
1398 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | 1399 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); |
1399 | while (towrite > 0) { | 1400 | while (towrite > 0) { |
1400 | tocopy = sb->s_blocksize - offset < towrite ? | 1401 | tocopy = sb->s_blocksize - offset < towrite ? |
1401 | sb->s_blocksize - offset : towrite; | 1402 | sb->s_blocksize - offset : towrite; |
1402 | 1403 | ||
1403 | bh = ufs_bread(inode, blk, 1, &err); | 1404 | bh = ufs_bread(inode, blk, 1, &err); |
1404 | if (!bh) | 1405 | if (!bh) |
1405 | goto out; | 1406 | goto out; |
1406 | lock_buffer(bh); | 1407 | lock_buffer(bh); |
1407 | memcpy(bh->b_data+offset, data, tocopy); | 1408 | memcpy(bh->b_data+offset, data, tocopy); |
1408 | flush_dcache_page(bh->b_page); | 1409 | flush_dcache_page(bh->b_page); |
1409 | set_buffer_uptodate(bh); | 1410 | set_buffer_uptodate(bh); |
1410 | mark_buffer_dirty(bh); | 1411 | mark_buffer_dirty(bh); |
1411 | unlock_buffer(bh); | 1412 | unlock_buffer(bh); |
1412 | brelse(bh); | 1413 | brelse(bh); |
1413 | offset = 0; | 1414 | offset = 0; |
1414 | towrite -= tocopy; | 1415 | towrite -= tocopy; |
1415 | data += tocopy; | 1416 | data += tocopy; |
1416 | blk++; | 1417 | blk++; |
1417 | } | 1418 | } |
1418 | out: | 1419 | out: |
1419 | if (len == towrite) { | 1420 | if (len == towrite) { |
1420 | mutex_unlock(&inode->i_mutex); | 1421 | mutex_unlock(&inode->i_mutex); |
1421 | return err; | 1422 | return err; |
1422 | } | 1423 | } |
1423 | if (inode->i_size < off+len-towrite) | 1424 | if (inode->i_size < off+len-towrite) |
1424 | i_size_write(inode, off+len-towrite); | 1425 | i_size_write(inode, off+len-towrite); |
1425 | inode->i_version++; | 1426 | inode->i_version++; |
1426 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 1427 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
1427 | mark_inode_dirty(inode); | 1428 | mark_inode_dirty(inode); |
1428 | mutex_unlock(&inode->i_mutex); | 1429 | mutex_unlock(&inode->i_mutex); |
1429 | return len - towrite; | 1430 | return len - towrite; |
1430 | } | 1431 | } |
1431 | 1432 | ||
1432 | #endif | 1433 | #endif |
1433 | 1434 | ||
1434 | static int ufs_get_sb(struct file_system_type *fs_type, | 1435 | static int ufs_get_sb(struct file_system_type *fs_type, |
1435 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 1436 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1436 | { | 1437 | { |
1437 | return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt); | 1438 | return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt); |
1438 | } | 1439 | } |
1439 | 1440 | ||
1440 | static struct file_system_type ufs_fs_type = { | 1441 | static struct file_system_type ufs_fs_type = { |
1441 | .owner = THIS_MODULE, | 1442 | .owner = THIS_MODULE, |
1442 | .name = "ufs", | 1443 | .name = "ufs", |
1443 | .get_sb = ufs_get_sb, | 1444 | .get_sb = ufs_get_sb, |
1444 | .kill_sb = kill_block_super, | 1445 | .kill_sb = kill_block_super, |
1445 | .fs_flags = FS_REQUIRES_DEV, | 1446 | .fs_flags = FS_REQUIRES_DEV, |
1446 | }; | 1447 | }; |
1447 | 1448 | ||
1448 | static int __init init_ufs_fs(void) | 1449 | static int __init init_ufs_fs(void) |
1449 | { | 1450 | { |
1450 | int err = init_inodecache(); | 1451 | int err = init_inodecache(); |
1451 | if (err) | 1452 | if (err) |
1452 | goto out1; | 1453 | goto out1; |
1453 | err = register_filesystem(&ufs_fs_type); | 1454 | err = register_filesystem(&ufs_fs_type); |
1454 | if (err) | 1455 | if (err) |
1455 | goto out; | 1456 | goto out; |
1456 | return 0; | 1457 | return 0; |
1457 | out: | 1458 | out: |
1458 | destroy_inodecache(); | 1459 | destroy_inodecache(); |
1459 | out1: | 1460 | out1: |
1460 | return err; | 1461 | return err; |
1461 | } | 1462 | } |
1462 | 1463 | ||
1463 | static void __exit exit_ufs_fs(void) | 1464 | static void __exit exit_ufs_fs(void) |
1464 | { | 1465 | { |
1465 | unregister_filesystem(&ufs_fs_type); | 1466 | unregister_filesystem(&ufs_fs_type); |
1466 | destroy_inodecache(); | 1467 | destroy_inodecache(); |
1467 | } | 1468 | } |
1468 | 1469 | ||
1469 | module_init(init_ufs_fs) | 1470 | module_init(init_ufs_fs) |
1470 | module_exit(exit_ufs_fs) | 1471 | module_exit(exit_ufs_fs) |
1471 | MODULE_LICENSE("GPL"); | 1472 | MODULE_LICENSE("GPL"); |
1472 | 1473 |
fs/ufs/symlink.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/symlink.c | 2 | * linux/fs/ufs/symlink.c |
3 | * | 3 | * |
4 | * Only fast symlinks left here - the rest is done by generic code. AV, 1999 | 4 | * Only fast symlinks left here - the rest is done by generic code. AV, 1999 |
5 | * | 5 | * |
6 | * Copyright (C) 1998 | 6 | * Copyright (C) 1998 |
7 | * Daniel Pirkl <daniel.pirkl@emai.cz> | 7 | * Daniel Pirkl <daniel.pirkl@emai.cz> |
8 | * Charles University, Faculty of Mathematics and Physics | 8 | * Charles University, Faculty of Mathematics and Physics |
9 | * | 9 | * |
10 | * from | 10 | * from |
11 | * | 11 | * |
12 | * linux/fs/ext2/symlink.c | 12 | * linux/fs/ext2/symlink.c |
13 | * | 13 | * |
14 | * Copyright (C) 1992, 1993, 1994, 1995 | 14 | * Copyright (C) 1992, 1993, 1994, 1995 |
15 | * Remy Card (card@masi.ibp.fr) | 15 | * Remy Card (card@masi.ibp.fr) |
16 | * Laboratoire MASI - Institut Blaise Pascal | 16 | * Laboratoire MASI - Institut Blaise Pascal |
17 | * Universite Pierre et Marie Curie (Paris VI) | 17 | * Universite Pierre et Marie Curie (Paris VI) |
18 | * | 18 | * |
19 | * from | 19 | * from |
20 | * | 20 | * |
21 | * linux/fs/minix/symlink.c | 21 | * linux/fs/minix/symlink.c |
22 | * | 22 | * |
23 | * Copyright (C) 1991, 1992 Linus Torvalds | 23 | * Copyright (C) 1991, 1992 Linus Torvalds |
24 | * | 24 | * |
25 | * ext2 symlink handling code | 25 | * ext2 symlink handling code |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/namei.h> | 29 | #include <linux/namei.h> |
30 | #include <linux/ufs_fs.h> | 30 | #include <linux/ufs_fs.h> |
31 | #include "ufs.h" | ||
32 | |||
31 | 33 | ||
32 | static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) | 34 | static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) |
33 | { | 35 | { |
34 | struct ufs_inode_info *p = UFS_I(dentry->d_inode); | 36 | struct ufs_inode_info *p = UFS_I(dentry->d_inode); |
35 | nd_set_link(nd, (char*)p->i_u1.i_symlink); | 37 | nd_set_link(nd, (char*)p->i_u1.i_symlink); |
36 | return NULL; | 38 | return NULL; |
37 | } | 39 | } |
38 | 40 | ||
39 | const struct inode_operations ufs_fast_symlink_inode_operations = { | 41 | const struct inode_operations ufs_fast_symlink_inode_operations = { |
40 | .readlink = generic_readlink, | 42 | .readlink = generic_readlink, |
41 | .follow_link = ufs_follow_link, | 43 | .follow_link = ufs_follow_link, |
42 | }; | 44 | }; |
43 | 45 |
fs/ufs/truncate.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/truncate.c | 2 | * linux/fs/ufs/truncate.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | * | 7 | * |
8 | * from | 8 | * from |
9 | * | 9 | * |
10 | * linux/fs/ext2/truncate.c | 10 | * linux/fs/ext2/truncate.c |
11 | * | 11 | * |
12 | * Copyright (C) 1992, 1993, 1994, 1995 | 12 | * Copyright (C) 1992, 1993, 1994, 1995 |
13 | * Remy Card (card@masi.ibp.fr) | 13 | * Remy Card (card@masi.ibp.fr) |
14 | * Laboratoire MASI - Institut Blaise Pascal | 14 | * Laboratoire MASI - Institut Blaise Pascal |
15 | * Universite Pierre et Marie Curie (Paris VI) | 15 | * Universite Pierre et Marie Curie (Paris VI) |
16 | * | 16 | * |
17 | * from | 17 | * from |
18 | * | 18 | * |
19 | * linux/fs/minix/truncate.c | 19 | * linux/fs/minix/truncate.c |
20 | * | 20 | * |
21 | * Copyright (C) 1991, 1992 Linus Torvalds | 21 | * Copyright (C) 1991, 1992 Linus Torvalds |
22 | * | 22 | * |
23 | * Big-endian to little-endian byte-swapping/bitmaps by | 23 | * Big-endian to little-endian byte-swapping/bitmaps by |
24 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 24 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
25 | */ | 25 | */ |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Real random numbers for secure rm added 94/02/18 | 28 | * Real random numbers for secure rm added 94/02/18 |
29 | * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr> | 29 | * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr> |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Adoptation to use page cache and UFS2 write support by | 33 | * Adoptation to use page cache and UFS2 write support by |
34 | * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 | 34 | * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
38 | #include <linux/fs.h> | 38 | #include <linux/fs.h> |
39 | #include <linux/ufs_fs.h> | 39 | #include <linux/ufs_fs.h> |
40 | #include <linux/fcntl.h> | 40 | #include <linux/fcntl.h> |
41 | #include <linux/time.h> | 41 | #include <linux/time.h> |
42 | #include <linux/stat.h> | 42 | #include <linux/stat.h> |
43 | #include <linux/string.h> | 43 | #include <linux/string.h> |
44 | #include <linux/smp_lock.h> | 44 | #include <linux/smp_lock.h> |
45 | #include <linux/buffer_head.h> | 45 | #include <linux/buffer_head.h> |
46 | #include <linux/blkdev.h> | 46 | #include <linux/blkdev.h> |
47 | #include <linux/sched.h> | 47 | #include <linux/sched.h> |
48 | 48 | ||
49 | #include "ufs.h" | ||
49 | #include "swab.h" | 50 | #include "swab.h" |
50 | #include "util.h" | 51 | #include "util.h" |
51 | 52 | ||
52 | /* | 53 | /* |
53 | * Secure deletion currently doesn't work. It interacts very badly | 54 | * Secure deletion currently doesn't work. It interacts very badly |
54 | * with buffers shared with memory mappings, and for that reason | 55 | * with buffers shared with memory mappings, and for that reason |
55 | * can't be done in the truncate() routines. It should instead be | 56 | * can't be done in the truncate() routines. It should instead be |
56 | * done separately in "release()" before calling the truncate routines | 57 | * done separately in "release()" before calling the truncate routines |
57 | * that will release the actual file blocks. | 58 | * that will release the actual file blocks. |
58 | * | 59 | * |
59 | * Linus | 60 | * Linus |
60 | */ | 61 | */ |
61 | 62 | ||
62 | #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) | 63 | #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) |
63 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) | 64 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) |
64 | 65 | ||
65 | 66 | ||
66 | static int ufs_trunc_direct(struct inode *inode) | 67 | static int ufs_trunc_direct(struct inode *inode) |
67 | { | 68 | { |
68 | struct ufs_inode_info *ufsi = UFS_I(inode); | 69 | struct ufs_inode_info *ufsi = UFS_I(inode); |
69 | struct super_block * sb; | 70 | struct super_block * sb; |
70 | struct ufs_sb_private_info * uspi; | 71 | struct ufs_sb_private_info * uspi; |
71 | void *p; | 72 | void *p; |
72 | u64 frag1, frag2, frag3, frag4, block1, block2; | 73 | u64 frag1, frag2, frag3, frag4, block1, block2; |
73 | unsigned frag_to_free, free_count; | 74 | unsigned frag_to_free, free_count; |
74 | unsigned i, tmp; | 75 | unsigned i, tmp; |
75 | int retry; | 76 | int retry; |
76 | 77 | ||
77 | UFSD("ENTER: ino %lu\n", inode->i_ino); | 78 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
78 | 79 | ||
79 | sb = inode->i_sb; | 80 | sb = inode->i_sb; |
80 | uspi = UFS_SB(sb)->s_uspi; | 81 | uspi = UFS_SB(sb)->s_uspi; |
81 | 82 | ||
82 | frag_to_free = 0; | 83 | frag_to_free = 0; |
83 | free_count = 0; | 84 | free_count = 0; |
84 | retry = 0; | 85 | retry = 0; |
85 | 86 | ||
86 | frag1 = DIRECT_FRAGMENT; | 87 | frag1 = DIRECT_FRAGMENT; |
87 | frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); | 88 | frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag); |
88 | frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); | 89 | frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1); |
89 | frag3 = frag4 & ~uspi->s_fpbmask; | 90 | frag3 = frag4 & ~uspi->s_fpbmask; |
90 | block1 = block2 = 0; | 91 | block1 = block2 = 0; |
91 | if (frag2 > frag3) { | 92 | if (frag2 > frag3) { |
92 | frag2 = frag4; | 93 | frag2 = frag4; |
93 | frag3 = frag4 = 0; | 94 | frag3 = frag4 = 0; |
94 | } else if (frag2 < frag3) { | 95 | } else if (frag2 < frag3) { |
95 | block1 = ufs_fragstoblks (frag2); | 96 | block1 = ufs_fragstoblks (frag2); |
96 | block2 = ufs_fragstoblks (frag3); | 97 | block2 = ufs_fragstoblks (frag3); |
97 | } | 98 | } |
98 | 99 | ||
99 | UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu," | 100 | UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu," |
100 | " frag3 %llu, frag4 %llu\n", inode->i_ino, | 101 | " frag3 %llu, frag4 %llu\n", inode->i_ino, |
101 | (unsigned long long)frag1, (unsigned long long)frag2, | 102 | (unsigned long long)frag1, (unsigned long long)frag2, |
102 | (unsigned long long)block1, (unsigned long long)block2, | 103 | (unsigned long long)block1, (unsigned long long)block2, |
103 | (unsigned long long)frag3, (unsigned long long)frag4); | 104 | (unsigned long long)frag3, (unsigned long long)frag4); |
104 | 105 | ||
105 | if (frag1 >= frag2) | 106 | if (frag1 >= frag2) |
106 | goto next1; | 107 | goto next1; |
107 | 108 | ||
108 | /* | 109 | /* |
109 | * Free first free fragments | 110 | * Free first free fragments |
110 | */ | 111 | */ |
111 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); | 112 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); |
112 | tmp = ufs_data_ptr_to_cpu(sb, p); | 113 | tmp = ufs_data_ptr_to_cpu(sb, p); |
113 | if (!tmp ) | 114 | if (!tmp ) |
114 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); | 115 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); |
115 | frag2 -= frag1; | 116 | frag2 -= frag1; |
116 | frag1 = ufs_fragnum (frag1); | 117 | frag1 = ufs_fragnum (frag1); |
117 | 118 | ||
118 | ufs_free_fragments(inode, tmp + frag1, frag2); | 119 | ufs_free_fragments(inode, tmp + frag1, frag2); |
119 | mark_inode_dirty(inode); | 120 | mark_inode_dirty(inode); |
120 | frag_to_free = tmp + frag1; | 121 | frag_to_free = tmp + frag1; |
121 | 122 | ||
122 | next1: | 123 | next1: |
123 | /* | 124 | /* |
124 | * Free whole blocks | 125 | * Free whole blocks |
125 | */ | 126 | */ |
126 | for (i = block1 ; i < block2; i++) { | 127 | for (i = block1 ; i < block2; i++) { |
127 | p = ufs_get_direct_data_ptr(uspi, ufsi, i); | 128 | p = ufs_get_direct_data_ptr(uspi, ufsi, i); |
128 | tmp = ufs_data_ptr_to_cpu(sb, p); | 129 | tmp = ufs_data_ptr_to_cpu(sb, p); |
129 | if (!tmp) | 130 | if (!tmp) |
130 | continue; | 131 | continue; |
131 | ufs_data_ptr_clear(uspi, p); | 132 | ufs_data_ptr_clear(uspi, p); |
132 | 133 | ||
133 | if (free_count == 0) { | 134 | if (free_count == 0) { |
134 | frag_to_free = tmp; | 135 | frag_to_free = tmp; |
135 | free_count = uspi->s_fpb; | 136 | free_count = uspi->s_fpb; |
136 | } else if (free_count > 0 && frag_to_free == tmp - free_count) | 137 | } else if (free_count > 0 && frag_to_free == tmp - free_count) |
137 | free_count += uspi->s_fpb; | 138 | free_count += uspi->s_fpb; |
138 | else { | 139 | else { |
139 | ufs_free_blocks (inode, frag_to_free, free_count); | 140 | ufs_free_blocks (inode, frag_to_free, free_count); |
140 | frag_to_free = tmp; | 141 | frag_to_free = tmp; |
141 | free_count = uspi->s_fpb; | 142 | free_count = uspi->s_fpb; |
142 | } | 143 | } |
143 | mark_inode_dirty(inode); | 144 | mark_inode_dirty(inode); |
144 | } | 145 | } |
145 | 146 | ||
146 | if (free_count > 0) | 147 | if (free_count > 0) |
147 | ufs_free_blocks (inode, frag_to_free, free_count); | 148 | ufs_free_blocks (inode, frag_to_free, free_count); |
148 | 149 | ||
149 | if (frag3 >= frag4) | 150 | if (frag3 >= frag4) |
150 | goto next3; | 151 | goto next3; |
151 | 152 | ||
152 | /* | 153 | /* |
153 | * Free last free fragments | 154 | * Free last free fragments |
154 | */ | 155 | */ |
155 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); | 156 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); |
156 | tmp = ufs_data_ptr_to_cpu(sb, p); | 157 | tmp = ufs_data_ptr_to_cpu(sb, p); |
157 | if (!tmp ) | 158 | if (!tmp ) |
158 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); | 159 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); |
159 | frag4 = ufs_fragnum (frag4); | 160 | frag4 = ufs_fragnum (frag4); |
160 | ufs_data_ptr_clear(uspi, p); | 161 | ufs_data_ptr_clear(uspi, p); |
161 | 162 | ||
162 | ufs_free_fragments (inode, tmp, frag4); | 163 | ufs_free_fragments (inode, tmp, frag4); |
163 | mark_inode_dirty(inode); | 164 | mark_inode_dirty(inode); |
164 | next3: | 165 | next3: |
165 | 166 | ||
166 | UFSD("EXIT: ino %lu\n", inode->i_ino); | 167 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
167 | return retry; | 168 | return retry; |
168 | } | 169 | } |
169 | 170 | ||
170 | 171 | ||
171 | static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) | 172 | static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) |
172 | { | 173 | { |
173 | struct super_block * sb; | 174 | struct super_block * sb; |
174 | struct ufs_sb_private_info * uspi; | 175 | struct ufs_sb_private_info * uspi; |
175 | struct ufs_buffer_head * ind_ubh; | 176 | struct ufs_buffer_head * ind_ubh; |
176 | void *ind; | 177 | void *ind; |
177 | u64 tmp, indirect_block, i, frag_to_free; | 178 | u64 tmp, indirect_block, i, frag_to_free; |
178 | unsigned free_count; | 179 | unsigned free_count; |
179 | int retry; | 180 | int retry; |
180 | 181 | ||
181 | UFSD("ENTER: ino %lu, offset %llu, p: %p\n", | 182 | UFSD("ENTER: ino %lu, offset %llu, p: %p\n", |
182 | inode->i_ino, (unsigned long long)offset, p); | 183 | inode->i_ino, (unsigned long long)offset, p); |
183 | 184 | ||
184 | BUG_ON(!p); | 185 | BUG_ON(!p); |
185 | 186 | ||
186 | sb = inode->i_sb; | 187 | sb = inode->i_sb; |
187 | uspi = UFS_SB(sb)->s_uspi; | 188 | uspi = UFS_SB(sb)->s_uspi; |
188 | 189 | ||
189 | frag_to_free = 0; | 190 | frag_to_free = 0; |
190 | free_count = 0; | 191 | free_count = 0; |
191 | retry = 0; | 192 | retry = 0; |
192 | 193 | ||
193 | tmp = ufs_data_ptr_to_cpu(sb, p); | 194 | tmp = ufs_data_ptr_to_cpu(sb, p); |
194 | if (!tmp) | 195 | if (!tmp) |
195 | return 0; | 196 | return 0; |
196 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); | 197 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); |
197 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { | 198 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
198 | ubh_brelse (ind_ubh); | 199 | ubh_brelse (ind_ubh); |
199 | return 1; | 200 | return 1; |
200 | } | 201 | } |
201 | if (!ind_ubh) { | 202 | if (!ind_ubh) { |
202 | ufs_data_ptr_clear(uspi, p); | 203 | ufs_data_ptr_clear(uspi, p); |
203 | return 0; | 204 | return 0; |
204 | } | 205 | } |
205 | 206 | ||
206 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; | 207 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; |
207 | for (i = indirect_block; i < uspi->s_apb; i++) { | 208 | for (i = indirect_block; i < uspi->s_apb; i++) { |
208 | ind = ubh_get_data_ptr(uspi, ind_ubh, i); | 209 | ind = ubh_get_data_ptr(uspi, ind_ubh, i); |
209 | tmp = ufs_data_ptr_to_cpu(sb, ind); | 210 | tmp = ufs_data_ptr_to_cpu(sb, ind); |
210 | if (!tmp) | 211 | if (!tmp) |
211 | continue; | 212 | continue; |
212 | 213 | ||
213 | ufs_data_ptr_clear(uspi, ind); | 214 | ufs_data_ptr_clear(uspi, ind); |
214 | ubh_mark_buffer_dirty(ind_ubh); | 215 | ubh_mark_buffer_dirty(ind_ubh); |
215 | if (free_count == 0) { | 216 | if (free_count == 0) { |
216 | frag_to_free = tmp; | 217 | frag_to_free = tmp; |
217 | free_count = uspi->s_fpb; | 218 | free_count = uspi->s_fpb; |
218 | } else if (free_count > 0 && frag_to_free == tmp - free_count) | 219 | } else if (free_count > 0 && frag_to_free == tmp - free_count) |
219 | free_count += uspi->s_fpb; | 220 | free_count += uspi->s_fpb; |
220 | else { | 221 | else { |
221 | ufs_free_blocks (inode, frag_to_free, free_count); | 222 | ufs_free_blocks (inode, frag_to_free, free_count); |
222 | frag_to_free = tmp; | 223 | frag_to_free = tmp; |
223 | free_count = uspi->s_fpb; | 224 | free_count = uspi->s_fpb; |
224 | } | 225 | } |
225 | 226 | ||
226 | mark_inode_dirty(inode); | 227 | mark_inode_dirty(inode); |
227 | } | 228 | } |
228 | 229 | ||
229 | if (free_count > 0) { | 230 | if (free_count > 0) { |
230 | ufs_free_blocks (inode, frag_to_free, free_count); | 231 | ufs_free_blocks (inode, frag_to_free, free_count); |
231 | } | 232 | } |
232 | for (i = 0; i < uspi->s_apb; i++) | 233 | for (i = 0; i < uspi->s_apb; i++) |
233 | if (!ufs_is_data_ptr_zero(uspi, | 234 | if (!ufs_is_data_ptr_zero(uspi, |
234 | ubh_get_data_ptr(uspi, ind_ubh, i))) | 235 | ubh_get_data_ptr(uspi, ind_ubh, i))) |
235 | break; | 236 | break; |
236 | if (i >= uspi->s_apb) { | 237 | if (i >= uspi->s_apb) { |
237 | tmp = ufs_data_ptr_to_cpu(sb, p); | 238 | tmp = ufs_data_ptr_to_cpu(sb, p); |
238 | ufs_data_ptr_clear(uspi, p); | 239 | ufs_data_ptr_clear(uspi, p); |
239 | 240 | ||
240 | ufs_free_blocks (inode, tmp, uspi->s_fpb); | 241 | ufs_free_blocks (inode, tmp, uspi->s_fpb); |
241 | mark_inode_dirty(inode); | 242 | mark_inode_dirty(inode); |
242 | ubh_bforget(ind_ubh); | 243 | ubh_bforget(ind_ubh); |
243 | ind_ubh = NULL; | 244 | ind_ubh = NULL; |
244 | } | 245 | } |
245 | if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) { | 246 | if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) { |
246 | ubh_ll_rw_block(SWRITE, ind_ubh); | 247 | ubh_ll_rw_block(SWRITE, ind_ubh); |
247 | ubh_wait_on_buffer (ind_ubh); | 248 | ubh_wait_on_buffer (ind_ubh); |
248 | } | 249 | } |
249 | ubh_brelse (ind_ubh); | 250 | ubh_brelse (ind_ubh); |
250 | 251 | ||
251 | UFSD("EXIT: ino %lu\n", inode->i_ino); | 252 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
252 | 253 | ||
253 | return retry; | 254 | return retry; |
254 | } | 255 | } |
255 | 256 | ||
256 | static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) | 257 | static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) |
257 | { | 258 | { |
258 | struct super_block * sb; | 259 | struct super_block * sb; |
259 | struct ufs_sb_private_info * uspi; | 260 | struct ufs_sb_private_info * uspi; |
260 | struct ufs_buffer_head *dind_bh; | 261 | struct ufs_buffer_head *dind_bh; |
261 | u64 i, tmp, dindirect_block; | 262 | u64 i, tmp, dindirect_block; |
262 | void *dind; | 263 | void *dind; |
263 | int retry = 0; | 264 | int retry = 0; |
264 | 265 | ||
265 | UFSD("ENTER: ino %lu\n", inode->i_ino); | 266 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
266 | 267 | ||
267 | sb = inode->i_sb; | 268 | sb = inode->i_sb; |
268 | uspi = UFS_SB(sb)->s_uspi; | 269 | uspi = UFS_SB(sb)->s_uspi; |
269 | 270 | ||
270 | dindirect_block = (DIRECT_BLOCK > offset) | 271 | dindirect_block = (DIRECT_BLOCK > offset) |
271 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; | 272 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; |
272 | retry = 0; | 273 | retry = 0; |
273 | 274 | ||
274 | tmp = ufs_data_ptr_to_cpu(sb, p); | 275 | tmp = ufs_data_ptr_to_cpu(sb, p); |
275 | if (!tmp) | 276 | if (!tmp) |
276 | return 0; | 277 | return 0; |
277 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); | 278 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); |
278 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { | 279 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
279 | ubh_brelse (dind_bh); | 280 | ubh_brelse (dind_bh); |
280 | return 1; | 281 | return 1; |
281 | } | 282 | } |
282 | if (!dind_bh) { | 283 | if (!dind_bh) { |
283 | ufs_data_ptr_clear(uspi, p); | 284 | ufs_data_ptr_clear(uspi, p); |
284 | return 0; | 285 | return 0; |
285 | } | 286 | } |
286 | 287 | ||
287 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { | 288 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { |
288 | dind = ubh_get_data_ptr(uspi, dind_bh, i); | 289 | dind = ubh_get_data_ptr(uspi, dind_bh, i); |
289 | tmp = ufs_data_ptr_to_cpu(sb, dind); | 290 | tmp = ufs_data_ptr_to_cpu(sb, dind); |
290 | if (!tmp) | 291 | if (!tmp) |
291 | continue; | 292 | continue; |
292 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); | 293 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); |
293 | ubh_mark_buffer_dirty(dind_bh); | 294 | ubh_mark_buffer_dirty(dind_bh); |
294 | } | 295 | } |
295 | 296 | ||
296 | for (i = 0; i < uspi->s_apb; i++) | 297 | for (i = 0; i < uspi->s_apb; i++) |
297 | if (!ufs_is_data_ptr_zero(uspi, | 298 | if (!ufs_is_data_ptr_zero(uspi, |
298 | ubh_get_data_ptr(uspi, dind_bh, i))) | 299 | ubh_get_data_ptr(uspi, dind_bh, i))) |
299 | break; | 300 | break; |
300 | if (i >= uspi->s_apb) { | 301 | if (i >= uspi->s_apb) { |
301 | tmp = ufs_data_ptr_to_cpu(sb, p); | 302 | tmp = ufs_data_ptr_to_cpu(sb, p); |
302 | ufs_data_ptr_clear(uspi, p); | 303 | ufs_data_ptr_clear(uspi, p); |
303 | 304 | ||
304 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 305 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
305 | mark_inode_dirty(inode); | 306 | mark_inode_dirty(inode); |
306 | ubh_bforget(dind_bh); | 307 | ubh_bforget(dind_bh); |
307 | dind_bh = NULL; | 308 | dind_bh = NULL; |
308 | } | 309 | } |
309 | if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { | 310 | if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { |
310 | ubh_ll_rw_block(SWRITE, dind_bh); | 311 | ubh_ll_rw_block(SWRITE, dind_bh); |
311 | ubh_wait_on_buffer (dind_bh); | 312 | ubh_wait_on_buffer (dind_bh); |
312 | } | 313 | } |
313 | ubh_brelse (dind_bh); | 314 | ubh_brelse (dind_bh); |
314 | 315 | ||
315 | UFSD("EXIT: ino %lu\n", inode->i_ino); | 316 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
316 | 317 | ||
317 | return retry; | 318 | return retry; |
318 | } | 319 | } |
319 | 320 | ||
320 | static int ufs_trunc_tindirect(struct inode *inode) | 321 | static int ufs_trunc_tindirect(struct inode *inode) |
321 | { | 322 | { |
322 | struct super_block *sb = inode->i_sb; | 323 | struct super_block *sb = inode->i_sb; |
323 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 324 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
324 | struct ufs_inode_info *ufsi = UFS_I(inode); | 325 | struct ufs_inode_info *ufsi = UFS_I(inode); |
325 | struct ufs_buffer_head * tind_bh; | 326 | struct ufs_buffer_head * tind_bh; |
326 | u64 tindirect_block, tmp, i; | 327 | u64 tindirect_block, tmp, i; |
327 | void *tind, *p; | 328 | void *tind, *p; |
328 | int retry; | 329 | int retry; |
329 | 330 | ||
330 | UFSD("ENTER: ino %lu\n", inode->i_ino); | 331 | UFSD("ENTER: ino %lu\n", inode->i_ino); |
331 | 332 | ||
332 | retry = 0; | 333 | retry = 0; |
333 | 334 | ||
334 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) | 335 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) |
335 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; | 336 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; |
336 | 337 | ||
337 | p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); | 338 | p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); |
338 | if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) | 339 | if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) |
339 | return 0; | 340 | return 0; |
340 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); | 341 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); |
341 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { | 342 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
342 | ubh_brelse (tind_bh); | 343 | ubh_brelse (tind_bh); |
343 | return 1; | 344 | return 1; |
344 | } | 345 | } |
345 | if (!tind_bh) { | 346 | if (!tind_bh) { |
346 | ufs_data_ptr_clear(uspi, p); | 347 | ufs_data_ptr_clear(uspi, p); |
347 | return 0; | 348 | return 0; |
348 | } | 349 | } |
349 | 350 | ||
350 | for (i = tindirect_block ; i < uspi->s_apb ; i++) { | 351 | for (i = tindirect_block ; i < uspi->s_apb ; i++) { |
351 | tind = ubh_get_data_ptr(uspi, tind_bh, i); | 352 | tind = ubh_get_data_ptr(uspi, tind_bh, i); |
352 | retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + | 353 | retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + |
353 | uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); | 354 | uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind); |
354 | ubh_mark_buffer_dirty(tind_bh); | 355 | ubh_mark_buffer_dirty(tind_bh); |
355 | } | 356 | } |
356 | for (i = 0; i < uspi->s_apb; i++) | 357 | for (i = 0; i < uspi->s_apb; i++) |
357 | if (!ufs_is_data_ptr_zero(uspi, | 358 | if (!ufs_is_data_ptr_zero(uspi, |
358 | ubh_get_data_ptr(uspi, tind_bh, i))) | 359 | ubh_get_data_ptr(uspi, tind_bh, i))) |
359 | break; | 360 | break; |
360 | if (i >= uspi->s_apb) { | 361 | if (i >= uspi->s_apb) { |
361 | tmp = ufs_data_ptr_to_cpu(sb, p); | 362 | tmp = ufs_data_ptr_to_cpu(sb, p); |
362 | ufs_data_ptr_clear(uspi, p); | 363 | ufs_data_ptr_clear(uspi, p); |
363 | 364 | ||
364 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 365 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
365 | mark_inode_dirty(inode); | 366 | mark_inode_dirty(inode); |
366 | ubh_bforget(tind_bh); | 367 | ubh_bforget(tind_bh); |
367 | tind_bh = NULL; | 368 | tind_bh = NULL; |
368 | } | 369 | } |
369 | if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { | 370 | if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { |
370 | ubh_ll_rw_block(SWRITE, tind_bh); | 371 | ubh_ll_rw_block(SWRITE, tind_bh); |
371 | ubh_wait_on_buffer (tind_bh); | 372 | ubh_wait_on_buffer (tind_bh); |
372 | } | 373 | } |
373 | ubh_brelse (tind_bh); | 374 | ubh_brelse (tind_bh); |
374 | 375 | ||
375 | UFSD("EXIT: ino %lu\n", inode->i_ino); | 376 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
376 | return retry; | 377 | return retry; |
377 | } | 378 | } |
378 | 379 | ||
379 | static int ufs_alloc_lastblock(struct inode *inode) | 380 | static int ufs_alloc_lastblock(struct inode *inode) |
380 | { | 381 | { |
381 | int err = 0; | 382 | int err = 0; |
382 | struct super_block *sb = inode->i_sb; | 383 | struct super_block *sb = inode->i_sb; |
383 | struct address_space *mapping = inode->i_mapping; | 384 | struct address_space *mapping = inode->i_mapping; |
384 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 385 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
385 | unsigned i, end; | 386 | unsigned i, end; |
386 | sector_t lastfrag; | 387 | sector_t lastfrag; |
387 | struct page *lastpage; | 388 | struct page *lastpage; |
388 | struct buffer_head *bh; | 389 | struct buffer_head *bh; |
389 | u64 phys64; | 390 | u64 phys64; |
390 | 391 | ||
391 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; | 392 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; |
392 | 393 | ||
393 | if (!lastfrag) | 394 | if (!lastfrag) |
394 | goto out; | 395 | goto out; |
395 | 396 | ||
396 | lastfrag--; | 397 | lastfrag--; |
397 | 398 | ||
398 | lastpage = ufs_get_locked_page(mapping, lastfrag >> | 399 | lastpage = ufs_get_locked_page(mapping, lastfrag >> |
399 | (PAGE_CACHE_SHIFT - inode->i_blkbits)); | 400 | (PAGE_CACHE_SHIFT - inode->i_blkbits)); |
400 | if (IS_ERR(lastpage)) { | 401 | if (IS_ERR(lastpage)) { |
401 | err = -EIO; | 402 | err = -EIO; |
402 | goto out; | 403 | goto out; |
403 | } | 404 | } |
404 | 405 | ||
405 | end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); | 406 | end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); |
406 | bh = page_buffers(lastpage); | 407 | bh = page_buffers(lastpage); |
407 | for (i = 0; i < end; ++i) | 408 | for (i = 0; i < end; ++i) |
408 | bh = bh->b_this_page; | 409 | bh = bh->b_this_page; |
409 | 410 | ||
410 | 411 | ||
411 | err = ufs_getfrag_block(inode, lastfrag, bh, 1); | 412 | err = ufs_getfrag_block(inode, lastfrag, bh, 1); |
412 | 413 | ||
413 | if (unlikely(err)) | 414 | if (unlikely(err)) |
414 | goto out_unlock; | 415 | goto out_unlock; |
415 | 416 | ||
416 | if (buffer_new(bh)) { | 417 | if (buffer_new(bh)) { |
417 | clear_buffer_new(bh); | 418 | clear_buffer_new(bh); |
418 | unmap_underlying_metadata(bh->b_bdev, | 419 | unmap_underlying_metadata(bh->b_bdev, |
419 | bh->b_blocknr); | 420 | bh->b_blocknr); |
420 | /* | 421 | /* |
421 | * we do not zeroize fragment, because of | 422 | * we do not zeroize fragment, because of |
422 | * if it maped to hole, it already contains zeroes | 423 | * if it maped to hole, it already contains zeroes |
423 | */ | 424 | */ |
424 | set_buffer_uptodate(bh); | 425 | set_buffer_uptodate(bh); |
425 | mark_buffer_dirty(bh); | 426 | mark_buffer_dirty(bh); |
426 | set_page_dirty(lastpage); | 427 | set_page_dirty(lastpage); |
427 | } | 428 | } |
428 | 429 | ||
429 | if (lastfrag >= UFS_IND_FRAGMENT) { | 430 | if (lastfrag >= UFS_IND_FRAGMENT) { |
430 | end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1; | 431 | end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1; |
431 | phys64 = bh->b_blocknr + 1; | 432 | phys64 = bh->b_blocknr + 1; |
432 | for (i = 0; i < end; ++i) { | 433 | for (i = 0; i < end; ++i) { |
433 | bh = sb_getblk(sb, i + phys64); | 434 | bh = sb_getblk(sb, i + phys64); |
434 | lock_buffer(bh); | 435 | lock_buffer(bh); |
435 | memset(bh->b_data, 0, sb->s_blocksize); | 436 | memset(bh->b_data, 0, sb->s_blocksize); |
436 | set_buffer_uptodate(bh); | 437 | set_buffer_uptodate(bh); |
437 | mark_buffer_dirty(bh); | 438 | mark_buffer_dirty(bh); |
438 | unlock_buffer(bh); | 439 | unlock_buffer(bh); |
439 | sync_dirty_buffer(bh); | 440 | sync_dirty_buffer(bh); |
440 | brelse(bh); | 441 | brelse(bh); |
441 | } | 442 | } |
442 | } | 443 | } |
443 | out_unlock: | 444 | out_unlock: |
444 | ufs_put_locked_page(lastpage); | 445 | ufs_put_locked_page(lastpage); |
445 | out: | 446 | out: |
446 | return err; | 447 | return err; |
447 | } | 448 | } |
448 | 449 | ||
449 | int ufs_truncate(struct inode *inode, loff_t old_i_size) | 450 | int ufs_truncate(struct inode *inode, loff_t old_i_size) |
450 | { | 451 | { |
451 | struct ufs_inode_info *ufsi = UFS_I(inode); | 452 | struct ufs_inode_info *ufsi = UFS_I(inode); |
452 | struct super_block *sb = inode->i_sb; | 453 | struct super_block *sb = inode->i_sb; |
453 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 454 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
454 | int retry, err = 0; | 455 | int retry, err = 0; |
455 | 456 | ||
456 | UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", | 457 | UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", |
457 | inode->i_ino, (unsigned long long)i_size_read(inode), | 458 | inode->i_ino, (unsigned long long)i_size_read(inode), |
458 | (unsigned long long)old_i_size); | 459 | (unsigned long long)old_i_size); |
459 | 460 | ||
460 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 461 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
461 | S_ISLNK(inode->i_mode))) | 462 | S_ISLNK(inode->i_mode))) |
462 | return -EINVAL; | 463 | return -EINVAL; |
463 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 464 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
464 | return -EPERM; | 465 | return -EPERM; |
465 | 466 | ||
466 | err = ufs_alloc_lastblock(inode); | 467 | err = ufs_alloc_lastblock(inode); |
467 | 468 | ||
468 | if (err) { | 469 | if (err) { |
469 | i_size_write(inode, old_i_size); | 470 | i_size_write(inode, old_i_size); |
470 | goto out; | 471 | goto out; |
471 | } | 472 | } |
472 | 473 | ||
473 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); | 474 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); |
474 | 475 | ||
475 | lock_kernel(); | 476 | lock_kernel(); |
476 | while (1) { | 477 | while (1) { |
477 | retry = ufs_trunc_direct(inode); | 478 | retry = ufs_trunc_direct(inode); |
478 | retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, | 479 | retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, |
479 | ufs_get_direct_data_ptr(uspi, ufsi, | 480 | ufs_get_direct_data_ptr(uspi, ufsi, |
480 | UFS_IND_BLOCK)); | 481 | UFS_IND_BLOCK)); |
481 | retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, | 482 | retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, |
482 | ufs_get_direct_data_ptr(uspi, ufsi, | 483 | ufs_get_direct_data_ptr(uspi, ufsi, |
483 | UFS_DIND_BLOCK)); | 484 | UFS_DIND_BLOCK)); |
484 | retry |= ufs_trunc_tindirect (inode); | 485 | retry |= ufs_trunc_tindirect (inode); |
485 | if (!retry) | 486 | if (!retry) |
486 | break; | 487 | break; |
487 | if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) | 488 | if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) |
488 | ufs_sync_inode (inode); | 489 | ufs_sync_inode (inode); |
489 | blk_run_address_space(inode->i_mapping); | 490 | blk_run_address_space(inode->i_mapping); |
490 | yield(); | 491 | yield(); |
491 | } | 492 | } |
492 | 493 | ||
493 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 494 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
494 | ufsi->i_lastfrag = DIRECT_FRAGMENT; | 495 | ufsi->i_lastfrag = DIRECT_FRAGMENT; |
495 | unlock_kernel(); | 496 | unlock_kernel(); |
496 | mark_inode_dirty(inode); | 497 | mark_inode_dirty(inode); |
497 | out: | 498 | out: |
498 | UFSD("EXIT: err %d\n", err); | 499 | UFSD("EXIT: err %d\n", err); |
499 | return err; | 500 | return err; |
500 | } | 501 | } |
501 | 502 | ||
502 | 503 | ||
503 | /* | 504 | /* |
504 | * We don't define our `inode->i_op->truncate', and call it here, | 505 | * We don't define our `inode->i_op->truncate', and call it here, |
505 | * because of: | 506 | * because of: |
506 | * - there is no way to know old size | 507 | * - there is no way to know old size |
507 | * - there is no way inform user about error, if it happens in `truncate' | 508 | * - there is no way inform user about error, if it happens in `truncate' |
508 | */ | 509 | */ |
509 | static int ufs_setattr(struct dentry *dentry, struct iattr *attr) | 510 | static int ufs_setattr(struct dentry *dentry, struct iattr *attr) |
510 | { | 511 | { |
511 | struct inode *inode = dentry->d_inode; | 512 | struct inode *inode = dentry->d_inode; |
512 | unsigned int ia_valid = attr->ia_valid; | 513 | unsigned int ia_valid = attr->ia_valid; |
513 | int error; | 514 | int error; |
514 | 515 | ||
515 | error = inode_change_ok(inode, attr); | 516 | error = inode_change_ok(inode, attr); |
516 | if (error) | 517 | if (error) |
517 | return error; | 518 | return error; |
518 | 519 | ||
519 | if (ia_valid & ATTR_SIZE && | 520 | if (ia_valid & ATTR_SIZE && |
520 | attr->ia_size != i_size_read(inode)) { | 521 | attr->ia_size != i_size_read(inode)) { |
521 | loff_t old_i_size = inode->i_size; | 522 | loff_t old_i_size = inode->i_size; |
522 | error = vmtruncate(inode, attr->ia_size); | 523 | error = vmtruncate(inode, attr->ia_size); |
523 | if (error) | 524 | if (error) |
524 | return error; | 525 | return error; |
525 | error = ufs_truncate(inode, old_i_size); | 526 | error = ufs_truncate(inode, old_i_size); |
526 | if (error) | 527 | if (error) |
527 | return error; | 528 | return error; |
528 | } | 529 | } |
529 | return inode_setattr(inode, attr); | 530 | return inode_setattr(inode, attr); |
530 | } | 531 | } |
531 | 532 | ||
532 | const struct inode_operations ufs_file_inode_operations = { | 533 | const struct inode_operations ufs_file_inode_operations = { |
533 | .setattr = ufs_setattr, | 534 | .setattr = ufs_setattr, |
534 | }; | 535 | }; |
535 | 536 |
fs/ufs/ufs.h
File was created | 1 | #ifndef _UFS_UFS_H | |
2 | #define _UFS_UFS_H 1 | ||
3 | |||
4 | #define UFS_MAX_GROUP_LOADED 8 | ||
5 | #define UFS_CGNO_EMPTY ((unsigned)-1) | ||
6 | |||
7 | struct ufs_sb_private_info; | ||
8 | struct ufs_cg_private_info; | ||
9 | struct ufs_csum; | ||
10 | |||
11 | struct ufs_sb_info { | ||
12 | struct ufs_sb_private_info * s_uspi; | ||
13 | struct ufs_csum * s_csp; | ||
14 | unsigned s_bytesex; | ||
15 | unsigned s_flags; | ||
16 | struct buffer_head ** s_ucg; | ||
17 | struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED]; | ||
18 | unsigned s_cgno[UFS_MAX_GROUP_LOADED]; | ||
19 | unsigned short s_cg_loaded; | ||
20 | unsigned s_mount_opt; | ||
21 | }; | ||
22 | |||
23 | struct ufs_inode_info { | ||
24 | union { | ||
25 | __fs32 i_data[15]; | ||
26 | __u8 i_symlink[4*15]; | ||
27 | __fs64 u2_i_data[15]; | ||
28 | } i_u1; | ||
29 | __u32 i_flags; | ||
30 | __u32 i_shadow; | ||
31 | __u32 i_unused1; | ||
32 | __u32 i_unused2; | ||
33 | __u32 i_oeftflag; | ||
34 | __u16 i_osync; | ||
35 | __u64 i_lastfrag; | ||
36 | __u32 i_dir_start_lookup; | ||
37 | struct inode vfs_inode; | ||
38 | }; | ||
39 | |||
40 | /* mount options */ | ||
41 | #define UFS_MOUNT_ONERROR 0x0000000F | ||
42 | #define UFS_MOUNT_ONERROR_PANIC 0x00000001 | ||
43 | #define UFS_MOUNT_ONERROR_LOCK 0x00000002 | ||
44 | #define UFS_MOUNT_ONERROR_UMOUNT 0x00000004 | ||
45 | #define UFS_MOUNT_ONERROR_REPAIR 0x00000008 | ||
46 | |||
47 | #define UFS_MOUNT_UFSTYPE 0x0000FFF0 | ||
48 | #define UFS_MOUNT_UFSTYPE_OLD 0x00000010 | ||
49 | #define UFS_MOUNT_UFSTYPE_44BSD 0x00000020 | ||
50 | #define UFS_MOUNT_UFSTYPE_SUN 0x00000040 | ||
51 | #define UFS_MOUNT_UFSTYPE_NEXTSTEP 0x00000080 | ||
52 | #define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100 | ||
53 | #define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200 | ||
54 | #define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400 | ||
55 | #define UFS_MOUNT_UFSTYPE_HP 0x00000800 | ||
56 | #define UFS_MOUNT_UFSTYPE_UFS2 0x00001000 | ||
57 | #define UFS_MOUNT_UFSTYPE_SUNOS 0x00002000 | ||
58 | |||
59 | #define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt | ||
60 | #define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt | ||
61 | #define ufs_test_opt(o,opt) ((o) & UFS_MOUNT_##opt) | ||
62 | |||
63 | /* | ||
64 | * Debug code | ||
65 | */ | ||
66 | #ifdef CONFIG_UFS_DEBUG | ||
67 | # define UFSD(f, a...) { \ | ||
68 | printk ("UFSD (%s, %d): %s:", \ | ||
69 | __FILE__, __LINE__, __FUNCTION__); \ | ||
70 | printk (f, ## a); \ | ||
71 | } | ||
72 | #else | ||
73 | # define UFSD(f, a...) /**/ | ||
74 | #endif | ||
75 | |||
76 | /* balloc.c */ | ||
77 | extern void ufs_free_fragments (struct inode *, u64, unsigned); | ||
78 | extern void ufs_free_blocks (struct inode *, u64, unsigned); | ||
79 | extern u64 ufs_new_fragments(struct inode *, void *, u64, u64, | ||
80 | unsigned, int *, struct page *); | ||
81 | |||
82 | /* cylinder.c */ | ||
83 | extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned); | ||
84 | extern void ufs_put_cylinder (struct super_block *, unsigned); | ||
85 | |||
86 | /* dir.c */ | ||
87 | extern const struct inode_operations ufs_dir_inode_operations; | ||
88 | extern int ufs_add_link (struct dentry *, struct inode *); | ||
89 | extern ino_t ufs_inode_by_name(struct inode *, struct dentry *); | ||
90 | extern int ufs_make_empty(struct inode *, struct inode *); | ||
91 | extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **); | ||
92 | extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *); | ||
93 | extern int ufs_empty_dir (struct inode *); | ||
94 | extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **); | ||
95 | extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, | ||
96 | struct page *page, struct inode *inode); | ||
97 | |||
98 | /* file.c */ | ||
99 | extern const struct inode_operations ufs_file_inode_operations; | ||
100 | extern const struct file_operations ufs_file_operations; | ||
101 | |||
102 | extern const struct address_space_operations ufs_aops; | ||
103 | |||
104 | /* ialloc.c */ | ||
105 | extern void ufs_free_inode (struct inode *inode); | ||
106 | extern struct inode * ufs_new_inode (struct inode *, int); | ||
107 | |||
108 | /* inode.c */ | ||
109 | extern void ufs_read_inode (struct inode *); | ||
110 | extern void ufs_put_inode (struct inode *); | ||
111 | extern int ufs_write_inode (struct inode *, int); | ||
112 | extern int ufs_sync_inode (struct inode *); | ||
113 | extern void ufs_delete_inode (struct inode *); | ||
114 | extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); | ||
115 | extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); | ||
116 | |||
117 | /* namei.c */ | ||
118 | extern const struct file_operations ufs_dir_operations; | ||
119 | |||
120 | /* super.c */ | ||
121 | extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
122 | extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
123 | extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
124 | |||
125 | /* symlink.c */ | ||
126 | extern const struct inode_operations ufs_fast_symlink_inode_operations; | ||
127 | |||
128 | /* truncate.c */ | ||
129 | extern int ufs_truncate (struct inode *, loff_t); | ||
130 | |||
131 | static inline struct ufs_sb_info *UFS_SB(struct super_block *sb) | ||
132 | { | ||
133 | return sb->s_fs_info; | ||
134 | } | ||
135 | |||
136 | static inline struct ufs_inode_info *UFS_I(struct inode *inode) | ||
137 | { | ||
138 | return container_of(inode, struct ufs_inode_info, vfs_inode); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * Give cylinder group number for a file system block. | ||
143 | * Give cylinder group block number for a file system block. | ||
144 | */ | ||
145 | /* #define ufs_dtog(d) ((d) / uspi->s_fpg) */ | ||
146 | static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b) | ||
147 | { | ||
148 | do_div(b, uspi->s_fpg); | ||
149 | return b; | ||
150 | } | ||
151 | /* #define ufs_dtogd(d) ((d) % uspi->s_fpg) */ | ||
152 | static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b) | ||
153 | { | ||
154 | return do_div(b, uspi->s_fpg); | ||
155 | } | ||
156 | |||
157 | #endif /* _UFS_UFS_H */ | ||
158 |
fs/ufs/util.c
1 | /* | 1 | /* |
2 | * linux/fs/ufs/util.c | 2 | * linux/fs/ufs/util.c |
3 | * | 3 | * |
4 | * Copyright (C) 1998 | 4 | * Copyright (C) 1998 |
5 | * Daniel Pirkl <daniel.pirkl@email.cz> | 5 | * Daniel Pirkl <daniel.pirkl@email.cz> |
6 | * Charles University, Faculty of Mathematics and Physics | 6 | * Charles University, Faculty of Mathematics and Physics |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/ufs_fs.h> | 11 | #include <linux/ufs_fs.h> |
12 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
13 | 13 | ||
14 | #include "ufs.h" | ||
14 | #include "swab.h" | 15 | #include "swab.h" |
15 | #include "util.h" | 16 | #include "util.h" |
16 | 17 | ||
17 | struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, | 18 | struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi, |
18 | struct super_block *sb, u64 fragment, u64 size) | 19 | struct super_block *sb, u64 fragment, u64 size) |
19 | { | 20 | { |
20 | struct ufs_buffer_head * ubh; | 21 | struct ufs_buffer_head * ubh; |
21 | unsigned i, j ; | 22 | unsigned i, j ; |
22 | u64 count = 0; | 23 | u64 count = 0; |
23 | if (size & ~uspi->s_fmask) | 24 | if (size & ~uspi->s_fmask) |
24 | return NULL; | 25 | return NULL; |
25 | count = size >> uspi->s_fshift; | 26 | count = size >> uspi->s_fshift; |
26 | if (count > UFS_MAXFRAG) | 27 | if (count > UFS_MAXFRAG) |
27 | return NULL; | 28 | return NULL; |
28 | ubh = (struct ufs_buffer_head *) | 29 | ubh = (struct ufs_buffer_head *) |
29 | kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL); | 30 | kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL); |
30 | if (!ubh) | 31 | if (!ubh) |
31 | return NULL; | 32 | return NULL; |
32 | ubh->fragment = fragment; | 33 | ubh->fragment = fragment; |
33 | ubh->count = count; | 34 | ubh->count = count; |
34 | for (i = 0; i < count; i++) | 35 | for (i = 0; i < count; i++) |
35 | if (!(ubh->bh[i] = sb_bread(sb, fragment + i))) | 36 | if (!(ubh->bh[i] = sb_bread(sb, fragment + i))) |
36 | goto failed; | 37 | goto failed; |
37 | for (; i < UFS_MAXFRAG; i++) | 38 | for (; i < UFS_MAXFRAG; i++) |
38 | ubh->bh[i] = NULL; | 39 | ubh->bh[i] = NULL; |
39 | return ubh; | 40 | return ubh; |
40 | failed: | 41 | failed: |
41 | for (j = 0; j < i; j++) | 42 | for (j = 0; j < i; j++) |
42 | brelse (ubh->bh[j]); | 43 | brelse (ubh->bh[j]); |
43 | kfree(ubh); | 44 | kfree(ubh); |
44 | return NULL; | 45 | return NULL; |
45 | } | 46 | } |
46 | 47 | ||
47 | struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi, | 48 | struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi, |
48 | struct super_block *sb, u64 fragment, u64 size) | 49 | struct super_block *sb, u64 fragment, u64 size) |
49 | { | 50 | { |
50 | unsigned i, j; | 51 | unsigned i, j; |
51 | u64 count = 0; | 52 | u64 count = 0; |
52 | if (size & ~uspi->s_fmask) | 53 | if (size & ~uspi->s_fmask) |
53 | return NULL; | 54 | return NULL; |
54 | count = size >> uspi->s_fshift; | 55 | count = size >> uspi->s_fshift; |
55 | if (count <= 0 || count > UFS_MAXFRAG) | 56 | if (count <= 0 || count > UFS_MAXFRAG) |
56 | return NULL; | 57 | return NULL; |
57 | USPI_UBH(uspi)->fragment = fragment; | 58 | USPI_UBH(uspi)->fragment = fragment; |
58 | USPI_UBH(uspi)->count = count; | 59 | USPI_UBH(uspi)->count = count; |
59 | for (i = 0; i < count; i++) | 60 | for (i = 0; i < count; i++) |
60 | if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i))) | 61 | if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i))) |
61 | goto failed; | 62 | goto failed; |
62 | for (; i < UFS_MAXFRAG; i++) | 63 | for (; i < UFS_MAXFRAG; i++) |
63 | USPI_UBH(uspi)->bh[i] = NULL; | 64 | USPI_UBH(uspi)->bh[i] = NULL; |
64 | return USPI_UBH(uspi); | 65 | return USPI_UBH(uspi); |
65 | failed: | 66 | failed: |
66 | for (j = 0; j < i; j++) | 67 | for (j = 0; j < i; j++) |
67 | brelse (USPI_UBH(uspi)->bh[j]); | 68 | brelse (USPI_UBH(uspi)->bh[j]); |
68 | return NULL; | 69 | return NULL; |
69 | } | 70 | } |
70 | 71 | ||
71 | void ubh_brelse (struct ufs_buffer_head * ubh) | 72 | void ubh_brelse (struct ufs_buffer_head * ubh) |
72 | { | 73 | { |
73 | unsigned i; | 74 | unsigned i; |
74 | if (!ubh) | 75 | if (!ubh) |
75 | return; | 76 | return; |
76 | for (i = 0; i < ubh->count; i++) | 77 | for (i = 0; i < ubh->count; i++) |
77 | brelse (ubh->bh[i]); | 78 | brelse (ubh->bh[i]); |
78 | kfree (ubh); | 79 | kfree (ubh); |
79 | } | 80 | } |
80 | 81 | ||
81 | void ubh_brelse_uspi (struct ufs_sb_private_info * uspi) | 82 | void ubh_brelse_uspi (struct ufs_sb_private_info * uspi) |
82 | { | 83 | { |
83 | unsigned i; | 84 | unsigned i; |
84 | if (!USPI_UBH(uspi)) | 85 | if (!USPI_UBH(uspi)) |
85 | return; | 86 | return; |
86 | for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) { | 87 | for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) { |
87 | brelse (USPI_UBH(uspi)->bh[i]); | 88 | brelse (USPI_UBH(uspi)->bh[i]); |
88 | USPI_UBH(uspi)->bh[i] = NULL; | 89 | USPI_UBH(uspi)->bh[i] = NULL; |
89 | } | 90 | } |
90 | } | 91 | } |
91 | 92 | ||
92 | void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh) | 93 | void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh) |
93 | { | 94 | { |
94 | unsigned i; | 95 | unsigned i; |
95 | if (!ubh) | 96 | if (!ubh) |
96 | return; | 97 | return; |
97 | for ( i = 0; i < ubh->count; i++ ) | 98 | for ( i = 0; i < ubh->count; i++ ) |
98 | mark_buffer_dirty (ubh->bh[i]); | 99 | mark_buffer_dirty (ubh->bh[i]); |
99 | } | 100 | } |
100 | 101 | ||
101 | void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag) | 102 | void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag) |
102 | { | 103 | { |
103 | unsigned i; | 104 | unsigned i; |
104 | if (!ubh) | 105 | if (!ubh) |
105 | return; | 106 | return; |
106 | if (flag) { | 107 | if (flag) { |
107 | for ( i = 0; i < ubh->count; i++ ) | 108 | for ( i = 0; i < ubh->count; i++ ) |
108 | set_buffer_uptodate (ubh->bh[i]); | 109 | set_buffer_uptodate (ubh->bh[i]); |
109 | } else { | 110 | } else { |
110 | for ( i = 0; i < ubh->count; i++ ) | 111 | for ( i = 0; i < ubh->count; i++ ) |
111 | clear_buffer_uptodate (ubh->bh[i]); | 112 | clear_buffer_uptodate (ubh->bh[i]); |
112 | } | 113 | } |
113 | } | 114 | } |
114 | 115 | ||
115 | void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh) | 116 | void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh) |
116 | { | 117 | { |
117 | if (!ubh) | 118 | if (!ubh) |
118 | return; | 119 | return; |
119 | 120 | ||
120 | ll_rw_block(rw, ubh->count, ubh->bh); | 121 | ll_rw_block(rw, ubh->count, ubh->bh); |
121 | } | 122 | } |
122 | 123 | ||
123 | void ubh_wait_on_buffer (struct ufs_buffer_head * ubh) | 124 | void ubh_wait_on_buffer (struct ufs_buffer_head * ubh) |
124 | { | 125 | { |
125 | unsigned i; | 126 | unsigned i; |
126 | if (!ubh) | 127 | if (!ubh) |
127 | return; | 128 | return; |
128 | for ( i = 0; i < ubh->count; i++ ) | 129 | for ( i = 0; i < ubh->count; i++ ) |
129 | wait_on_buffer (ubh->bh[i]); | 130 | wait_on_buffer (ubh->bh[i]); |
130 | } | 131 | } |
131 | 132 | ||
132 | void ubh_bforget (struct ufs_buffer_head * ubh) | 133 | void ubh_bforget (struct ufs_buffer_head * ubh) |
133 | { | 134 | { |
134 | unsigned i; | 135 | unsigned i; |
135 | if (!ubh) | 136 | if (!ubh) |
136 | return; | 137 | return; |
137 | for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) | 138 | for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) |
138 | bforget (ubh->bh[i]); | 139 | bforget (ubh->bh[i]); |
139 | } | 140 | } |
140 | 141 | ||
141 | int ubh_buffer_dirty (struct ufs_buffer_head * ubh) | 142 | int ubh_buffer_dirty (struct ufs_buffer_head * ubh) |
142 | { | 143 | { |
143 | unsigned i; | 144 | unsigned i; |
144 | unsigned result = 0; | 145 | unsigned result = 0; |
145 | if (!ubh) | 146 | if (!ubh) |
146 | return 0; | 147 | return 0; |
147 | for ( i = 0; i < ubh->count; i++ ) | 148 | for ( i = 0; i < ubh->count; i++ ) |
148 | result |= buffer_dirty(ubh->bh[i]); | 149 | result |= buffer_dirty(ubh->bh[i]); |
149 | return result; | 150 | return result; |
150 | } | 151 | } |
151 | 152 | ||
152 | void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, | 153 | void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, |
153 | unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size) | 154 | unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size) |
154 | { | 155 | { |
155 | unsigned len, bhno; | 156 | unsigned len, bhno; |
156 | if (size > (ubh->count << uspi->s_fshift)) | 157 | if (size > (ubh->count << uspi->s_fshift)) |
157 | size = ubh->count << uspi->s_fshift; | 158 | size = ubh->count << uspi->s_fshift; |
158 | bhno = 0; | 159 | bhno = 0; |
159 | while (size) { | 160 | while (size) { |
160 | len = min_t(unsigned int, size, uspi->s_fsize); | 161 | len = min_t(unsigned int, size, uspi->s_fsize); |
161 | memcpy (mem, ubh->bh[bhno]->b_data, len); | 162 | memcpy (mem, ubh->bh[bhno]->b_data, len); |
162 | mem += uspi->s_fsize; | 163 | mem += uspi->s_fsize; |
163 | size -= len; | 164 | size -= len; |
164 | bhno++; | 165 | bhno++; |
165 | } | 166 | } |
166 | } | 167 | } |
167 | 168 | ||
168 | void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, | 169 | void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, |
169 | struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size) | 170 | struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size) |
170 | { | 171 | { |
171 | unsigned len, bhno; | 172 | unsigned len, bhno; |
172 | if (size > (ubh->count << uspi->s_fshift)) | 173 | if (size > (ubh->count << uspi->s_fshift)) |
173 | size = ubh->count << uspi->s_fshift; | 174 | size = ubh->count << uspi->s_fshift; |
174 | bhno = 0; | 175 | bhno = 0; |
175 | while (size) { | 176 | while (size) { |
176 | len = min_t(unsigned int, size, uspi->s_fsize); | 177 | len = min_t(unsigned int, size, uspi->s_fsize); |
177 | memcpy (ubh->bh[bhno]->b_data, mem, len); | 178 | memcpy (ubh->bh[bhno]->b_data, mem, len); |
178 | mem += uspi->s_fsize; | 179 | mem += uspi->s_fsize; |
179 | size -= len; | 180 | size -= len; |
180 | bhno++; | 181 | bhno++; |
181 | } | 182 | } |
182 | } | 183 | } |
183 | 184 | ||
184 | dev_t | 185 | dev_t |
185 | ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi) | 186 | ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi) |
186 | { | 187 | { |
187 | __u32 fs32; | 188 | __u32 fs32; |
188 | dev_t dev; | 189 | dev_t dev; |
189 | 190 | ||
190 | if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 191 | if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
191 | fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]); | 192 | fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]); |
192 | else | 193 | else |
193 | fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]); | 194 | fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]); |
194 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | 195 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { |
195 | case UFS_ST_SUNx86: | 196 | case UFS_ST_SUNx86: |
196 | case UFS_ST_SUN: | 197 | case UFS_ST_SUN: |
197 | if ((fs32 & 0xffff0000) == 0 || | 198 | if ((fs32 & 0xffff0000) == 0 || |
198 | (fs32 & 0xffff0000) == 0xffff0000) | 199 | (fs32 & 0xffff0000) == 0xffff0000) |
199 | dev = old_decode_dev(fs32 & 0x7fff); | 200 | dev = old_decode_dev(fs32 & 0x7fff); |
200 | else | 201 | else |
201 | dev = MKDEV(sysv_major(fs32), sysv_minor(fs32)); | 202 | dev = MKDEV(sysv_major(fs32), sysv_minor(fs32)); |
202 | break; | 203 | break; |
203 | 204 | ||
204 | default: | 205 | default: |
205 | dev = old_decode_dev(fs32); | 206 | dev = old_decode_dev(fs32); |
206 | break; | 207 | break; |
207 | } | 208 | } |
208 | return dev; | 209 | return dev; |
209 | } | 210 | } |
210 | 211 | ||
211 | void | 212 | void |
212 | ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev) | 213 | ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev) |
213 | { | 214 | { |
214 | __u32 fs32; | 215 | __u32 fs32; |
215 | 216 | ||
216 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { | 217 | switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { |
217 | case UFS_ST_SUNx86: | 218 | case UFS_ST_SUNx86: |
218 | case UFS_ST_SUN: | 219 | case UFS_ST_SUN: |
219 | fs32 = sysv_encode_dev(dev); | 220 | fs32 = sysv_encode_dev(dev); |
220 | if ((fs32 & 0xffff8000) == 0) { | 221 | if ((fs32 & 0xffff8000) == 0) { |
221 | fs32 = old_encode_dev(dev); | 222 | fs32 = old_encode_dev(dev); |
222 | } | 223 | } |
223 | break; | 224 | break; |
224 | 225 | ||
225 | default: | 226 | default: |
226 | fs32 = old_encode_dev(dev); | 227 | fs32 = old_encode_dev(dev); |
227 | break; | 228 | break; |
228 | } | 229 | } |
229 | if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 230 | if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
230 | ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32); | 231 | ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32); |
231 | else | 232 | else |
232 | ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32); | 233 | ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32); |
233 | } | 234 | } |
234 | 235 | ||
235 | /** | 236 | /** |
236 | * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist | 237 | * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist |
237 | * read it from disk. | 238 | * read it from disk. |
238 | * @mapping: the address_space to search | 239 | * @mapping: the address_space to search |
239 | * @index: the page index | 240 | * @index: the page index |
240 | * | 241 | * |
241 | * Locates the desired pagecache page, if not exist we'll read it, | 242 | * Locates the desired pagecache page, if not exist we'll read it, |
242 | * locks it, increments its reference | 243 | * locks it, increments its reference |
243 | * count and returns its address. | 244 | * count and returns its address. |
244 | * | 245 | * |
245 | */ | 246 | */ |
246 | 247 | ||
247 | struct page *ufs_get_locked_page(struct address_space *mapping, | 248 | struct page *ufs_get_locked_page(struct address_space *mapping, |
248 | pgoff_t index) | 249 | pgoff_t index) |
249 | { | 250 | { |
250 | struct page *page; | 251 | struct page *page; |
251 | 252 | ||
252 | page = find_lock_page(mapping, index); | 253 | page = find_lock_page(mapping, index); |
253 | if (!page) { | 254 | if (!page) { |
254 | page = read_mapping_page(mapping, index, NULL); | 255 | page = read_mapping_page(mapping, index, NULL); |
255 | 256 | ||
256 | if (IS_ERR(page)) { | 257 | if (IS_ERR(page)) { |
257 | printk(KERN_ERR "ufs_change_blocknr: " | 258 | printk(KERN_ERR "ufs_change_blocknr: " |
258 | "read_mapping_page error: ino %lu, index: %lu\n", | 259 | "read_mapping_page error: ino %lu, index: %lu\n", |
259 | mapping->host->i_ino, index); | 260 | mapping->host->i_ino, index); |
260 | goto out; | 261 | goto out; |
261 | } | 262 | } |
262 | 263 | ||
263 | lock_page(page); | 264 | lock_page(page); |
264 | 265 | ||
265 | if (unlikely(page->mapping == NULL)) { | 266 | if (unlikely(page->mapping == NULL)) { |
266 | /* Truncate got there first */ | 267 | /* Truncate got there first */ |
267 | unlock_page(page); | 268 | unlock_page(page); |
268 | page_cache_release(page); | 269 | page_cache_release(page); |
269 | page = NULL; | 270 | page = NULL; |
270 | goto out; | 271 | goto out; |
271 | } | 272 | } |
272 | 273 | ||
273 | if (!PageUptodate(page) || PageError(page)) { | 274 | if (!PageUptodate(page) || PageError(page)) { |
274 | unlock_page(page); | 275 | unlock_page(page); |
275 | page_cache_release(page); | 276 | page_cache_release(page); |
276 | 277 | ||
277 | printk(KERN_ERR "ufs_change_blocknr: " | 278 | printk(KERN_ERR "ufs_change_blocknr: " |
278 | "can not read page: ino %lu, index: %lu\n", | 279 | "can not read page: ino %lu, index: %lu\n", |
279 | mapping->host->i_ino, index); | 280 | mapping->host->i_ino, index); |
280 | 281 | ||
281 | page = ERR_PTR(-EIO); | 282 | page = ERR_PTR(-EIO); |
282 | } | 283 | } |
283 | } | 284 | } |
284 | out: | 285 | out: |
285 | return page; | 286 | return page; |
286 | } | 287 | } |
287 | 288 |
include/linux/ufs_fs.h
1 | /* | 1 | /* |
2 | * linux/include/linux/ufs_fs.h | 2 | * linux/include/linux/ufs_fs.h |
3 | * | 3 | * |
4 | * Copyright (C) 1996 | 4 | * Copyright (C) 1996 |
5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) | 5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) |
6 | * Laboratory for Computer Science Research Computing Facility | 6 | * Laboratory for Computer Science Research Computing Facility |
7 | * Rutgers, The State University of New Jersey | 7 | * Rutgers, The State University of New Jersey |
8 | * | 8 | * |
9 | * Clean swab support by Fare <fare@tunes.org> | 9 | * Clean swab support by Fare <fare@tunes.org> |
10 | * just hope no one is using NNUUXXI on __?64 structure elements | 10 | * just hope no one is using NNUUXXI on __?64 structure elements |
11 | * 64-bit clean thanks to Maciej W. Rozycki <macro@ds2.pg.gda.pl> | 11 | * 64-bit clean thanks to Maciej W. Rozycki <macro@ds2.pg.gda.pl> |
12 | * | 12 | * |
13 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by | 13 | * 4.4BSD (FreeBSD) support added on February 1st 1998 by |
14 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based | 14 | * Niels Kristian Bech Jensen <nkbj@image.dk> partially based |
15 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. | 15 | * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. |
16 | * | 16 | * |
17 | * NeXTstep support added on February 5th 1998 by | 17 | * NeXTstep support added on February 5th 1998 by |
18 | * Niels Kristian Bech Jensen <nkbj@image.dk>. | 18 | * Niels Kristian Bech Jensen <nkbj@image.dk>. |
19 | * | 19 | * |
20 | * Write support by Daniel Pirkl <daniel.pirkl@email.cz> | 20 | * Write support by Daniel Pirkl <daniel.pirkl@email.cz> |
21 | * | 21 | * |
22 | * HP/UX hfs filesystem support added by | 22 | * HP/UX hfs filesystem support added by |
23 | * Martin K. Petersen <mkp@mkp.net>, August 1999 | 23 | * Martin K. Petersen <mkp@mkp.net>, August 1999 |
24 | * | 24 | * |
25 | * UFS2 (of FreeBSD 5.x) support added by | 25 | * UFS2 (of FreeBSD 5.x) support added by |
26 | * Niraj Kumar <niraj17@iitbombay.org> , Jan 2004 | 26 | * Niraj Kumar <niraj17@iitbombay.org> , Jan 2004 |
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #ifndef __LINUX_UFS_FS_H | 30 | #ifndef __LINUX_UFS_FS_H |
31 | #define __LINUX_UFS_FS_H | 31 | #define __LINUX_UFS_FS_H |
32 | 32 | ||
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/stat.h> | 35 | #include <linux/stat.h> |
36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
37 | 37 | ||
38 | #ifndef __KERNEL__ | 38 | #ifndef __KERNEL__ |
39 | typedef __u64 __fs64; | 39 | typedef __u64 __fs64; |
40 | typedef __u32 __fs32; | 40 | typedef __u32 __fs32; |
41 | typedef __u16 __fs16; | 41 | typedef __u16 __fs16; |
42 | #else | 42 | #else |
43 | #include <asm/div64.h> | 43 | #include <asm/div64.h> |
44 | typedef __u64 __bitwise __fs64; | 44 | typedef __u64 __bitwise __fs64; |
45 | typedef __u32 __bitwise __fs32; | 45 | typedef __u32 __bitwise __fs32; |
46 | typedef __u16 __bitwise __fs16; | 46 | typedef __u16 __bitwise __fs16; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifdef __KERNEL__ | ||
50 | #include <linux/ufs_fs_i.h> | ||
51 | #include <linux/ufs_fs_sb.h> | ||
52 | #endif | ||
53 | |||
54 | #define UFS_BBLOCK 0 | 49 | #define UFS_BBLOCK 0 |
55 | #define UFS_BBSIZE 8192 | 50 | #define UFS_BBSIZE 8192 |
56 | #define UFS_SBLOCK 8192 | 51 | #define UFS_SBLOCK 8192 |
57 | #define UFS_SBSIZE 8192 | 52 | #define UFS_SBSIZE 8192 |
58 | 53 | ||
59 | #define UFS_SECTOR_SIZE 512 | 54 | #define UFS_SECTOR_SIZE 512 |
60 | #define UFS_SECTOR_BITS 9 | 55 | #define UFS_SECTOR_BITS 9 |
61 | #define UFS_MAGIC 0x00011954 | 56 | #define UFS_MAGIC 0x00011954 |
62 | #define UFS2_MAGIC 0x19540119 | 57 | #define UFS2_MAGIC 0x19540119 |
63 | #define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ | 58 | #define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ |
64 | 59 | ||
65 | /* Copied from FreeBSD */ | 60 | /* Copied from FreeBSD */ |
66 | /* | 61 | /* |
67 | * Each disk drive contains some number of filesystems. | 62 | * Each disk drive contains some number of filesystems. |
68 | * A filesystem consists of a number of cylinder groups. | 63 | * A filesystem consists of a number of cylinder groups. |
69 | * Each cylinder group has inodes and data. | 64 | * Each cylinder group has inodes and data. |
70 | * | 65 | * |
71 | * A filesystem is described by its super-block, which in turn | 66 | * A filesystem is described by its super-block, which in turn |
72 | * describes the cylinder groups. The super-block is critical | 67 | * describes the cylinder groups. The super-block is critical |
73 | * data and is replicated in each cylinder group to protect against | 68 | * data and is replicated in each cylinder group to protect against |
74 | * catastrophic loss. This is done at `newfs' time and the critical | 69 | * catastrophic loss. This is done at `newfs' time and the critical |
75 | * super-block data does not change, so the copies need not be | 70 | * super-block data does not change, so the copies need not be |
76 | * referenced further unless disaster strikes. | 71 | * referenced further unless disaster strikes. |
77 | * | 72 | * |
78 | * For filesystem fs, the offsets of the various blocks of interest | 73 | * For filesystem fs, the offsets of the various blocks of interest |
79 | * are given in the super block as: | 74 | * are given in the super block as: |
80 | * [fs->fs_sblkno] Super-block | 75 | * [fs->fs_sblkno] Super-block |
81 | * [fs->fs_cblkno] Cylinder group block | 76 | * [fs->fs_cblkno] Cylinder group block |
82 | * [fs->fs_iblkno] Inode blocks | 77 | * [fs->fs_iblkno] Inode blocks |
83 | * [fs->fs_dblkno] Data blocks | 78 | * [fs->fs_dblkno] Data blocks |
84 | * The beginning of cylinder group cg in fs, is given by | 79 | * The beginning of cylinder group cg in fs, is given by |
85 | * the ``cgbase(fs, cg)'' macro. | 80 | * the ``cgbase(fs, cg)'' macro. |
86 | * | 81 | * |
87 | * Depending on the architecture and the media, the superblock may | 82 | * Depending on the architecture and the media, the superblock may |
88 | * reside in any one of four places. For tiny media where every block | 83 | * reside in any one of four places. For tiny media where every block |
89 | * counts, it is placed at the very front of the partition. Historically, | 84 | * counts, it is placed at the very front of the partition. Historically, |
90 | * UFS1 placed it 8K from the front to leave room for the disk label and | 85 | * UFS1 placed it 8K from the front to leave room for the disk label and |
91 | * a small bootstrap. For UFS2 it got moved to 64K from the front to leave | 86 | * a small bootstrap. For UFS2 it got moved to 64K from the front to leave |
92 | * room for the disk label and a bigger bootstrap, and for really piggy | 87 | * room for the disk label and a bigger bootstrap, and for really piggy |
93 | * systems we check at 256K from the front if the first three fail. In | 88 | * systems we check at 256K from the front if the first three fail. In |
94 | * all cases the size of the superblock will be SBLOCKSIZE. All values are | 89 | * all cases the size of the superblock will be SBLOCKSIZE. All values are |
95 | * given in byte-offset form, so they do not imply a sector size. The | 90 | * given in byte-offset form, so they do not imply a sector size. The |
96 | * SBLOCKSEARCH specifies the order in which the locations should be searched. | 91 | * SBLOCKSEARCH specifies the order in which the locations should be searched. |
97 | */ | 92 | */ |
98 | #define SBLOCK_FLOPPY 0 | 93 | #define SBLOCK_FLOPPY 0 |
99 | #define SBLOCK_UFS1 8192 | 94 | #define SBLOCK_UFS1 8192 |
100 | #define SBLOCK_UFS2 65536 | 95 | #define SBLOCK_UFS2 65536 |
101 | #define SBLOCK_PIGGY 262144 | 96 | #define SBLOCK_PIGGY 262144 |
102 | #define SBLOCKSIZE 8192 | 97 | #define SBLOCKSIZE 8192 |
103 | #define SBLOCKSEARCH \ | 98 | #define SBLOCKSEARCH \ |
104 | { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } | 99 | { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } |
105 | 100 | ||
106 | 101 | ||
107 | /* HP specific MAGIC values */ | 102 | /* HP specific MAGIC values */ |
108 | 103 | ||
109 | #define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ | 104 | #define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ |
110 | #define UFS_CIGAM_LFN 0x14500900 /* srahc 41 < semanelif stroppus sf */ | 105 | #define UFS_CIGAM_LFN 0x14500900 /* srahc 41 < semanelif stroppus sf */ |
111 | 106 | ||
112 | #define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ | 107 | #define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ |
113 | #define UFS_CIGAM_SEC 0x95216100 | 108 | #define UFS_CIGAM_SEC 0x95216100 |
114 | 109 | ||
115 | #define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ | 110 | #define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ |
116 | #define UFS_CIGAM_FEA 0x12561900 | 111 | #define UFS_CIGAM_FEA 0x12561900 |
117 | 112 | ||
118 | #define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ | 113 | #define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ |
119 | #define UFS_CIGAM_4GB 0x94192305 | 114 | #define UFS_CIGAM_4GB 0x94192305 |
120 | 115 | ||
121 | /* Seems somebody at HP goofed here. B1 and lfs are both 0x2 !?! */ | 116 | /* Seems somebody at HP goofed here. B1 and lfs are both 0x2 !?! */ |
122 | #define UFS_FSF_LFN 0x00000001 /* long file names */ | 117 | #define UFS_FSF_LFN 0x00000001 /* long file names */ |
123 | #define UFS_FSF_B1 0x00000002 /* B1 security */ | 118 | #define UFS_FSF_B1 0x00000002 /* B1 security */ |
124 | #define UFS_FSF_LFS 0x00000002 /* large files */ | 119 | #define UFS_FSF_LFS 0x00000002 /* large files */ |
125 | #define UFS_FSF_LUID 0x00000004 /* large UIDs */ | 120 | #define UFS_FSF_LUID 0x00000004 /* large UIDs */ |
126 | 121 | ||
127 | /* End of HP stuff */ | 122 | /* End of HP stuff */ |
128 | 123 | ||
129 | 124 | ||
130 | #define UFS_BSIZE 8192 | 125 | #define UFS_BSIZE 8192 |
131 | #define UFS_MINBSIZE 4096 | 126 | #define UFS_MINBSIZE 4096 |
132 | #define UFS_FSIZE 1024 | 127 | #define UFS_FSIZE 1024 |
133 | #define UFS_MAXFRAG (UFS_BSIZE / UFS_FSIZE) | 128 | #define UFS_MAXFRAG (UFS_BSIZE / UFS_FSIZE) |
134 | 129 | ||
135 | #define UFS_NDADDR 12 | 130 | #define UFS_NDADDR 12 |
136 | #define UFS_NINDIR 3 | 131 | #define UFS_NINDIR 3 |
137 | 132 | ||
138 | #define UFS_IND_BLOCK (UFS_NDADDR + 0) | 133 | #define UFS_IND_BLOCK (UFS_NDADDR + 0) |
139 | #define UFS_DIND_BLOCK (UFS_NDADDR + 1) | 134 | #define UFS_DIND_BLOCK (UFS_NDADDR + 1) |
140 | #define UFS_TIND_BLOCK (UFS_NDADDR + 2) | 135 | #define UFS_TIND_BLOCK (UFS_NDADDR + 2) |
141 | 136 | ||
142 | #define UFS_NDIR_FRAGMENT (UFS_NDADDR << uspi->s_fpbshift) | 137 | #define UFS_NDIR_FRAGMENT (UFS_NDADDR << uspi->s_fpbshift) |
143 | #define UFS_IND_FRAGMENT (UFS_IND_BLOCK << uspi->s_fpbshift) | 138 | #define UFS_IND_FRAGMENT (UFS_IND_BLOCK << uspi->s_fpbshift) |
144 | #define UFS_DIND_FRAGMENT (UFS_DIND_BLOCK << uspi->s_fpbshift) | 139 | #define UFS_DIND_FRAGMENT (UFS_DIND_BLOCK << uspi->s_fpbshift) |
145 | #define UFS_TIND_FRAGMENT (UFS_TIND_BLOCK << uspi->s_fpbshift) | 140 | #define UFS_TIND_FRAGMENT (UFS_TIND_BLOCK << uspi->s_fpbshift) |
146 | 141 | ||
147 | #define UFS_ROOTINO 2 | 142 | #define UFS_ROOTINO 2 |
148 | #define UFS_FIRST_INO (UFS_ROOTINO + 1) | 143 | #define UFS_FIRST_INO (UFS_ROOTINO + 1) |
149 | 144 | ||
150 | #define UFS_USEEFT ((__u16)65535) | 145 | #define UFS_USEEFT ((__u16)65535) |
151 | 146 | ||
152 | #define UFS_FSOK 0x7c269d38 | 147 | #define UFS_FSOK 0x7c269d38 |
153 | #define UFS_FSACTIVE ((__s8)0x00) | 148 | #define UFS_FSACTIVE ((__s8)0x00) |
154 | #define UFS_FSCLEAN ((__s8)0x01) | 149 | #define UFS_FSCLEAN ((__s8)0x01) |
155 | #define UFS_FSSTABLE ((__s8)0x02) | 150 | #define UFS_FSSTABLE ((__s8)0x02) |
156 | #define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ | 151 | #define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ |
157 | #define UFS_FSBAD ((__s8)0xff) | 152 | #define UFS_FSBAD ((__s8)0xff) |
158 | 153 | ||
159 | /* From here to next blank line, s_flags for ufs_sb_info */ | 154 | /* From here to next blank line, s_flags for ufs_sb_info */ |
160 | /* directory entry encoding */ | 155 | /* directory entry encoding */ |
161 | #define UFS_DE_MASK 0x00000010 /* mask for the following */ | 156 | #define UFS_DE_MASK 0x00000010 /* mask for the following */ |
162 | #define UFS_DE_OLD 0x00000000 | 157 | #define UFS_DE_OLD 0x00000000 |
163 | #define UFS_DE_44BSD 0x00000010 | 158 | #define UFS_DE_44BSD 0x00000010 |
164 | /* uid encoding */ | 159 | /* uid encoding */ |
165 | #define UFS_UID_MASK 0x00000060 /* mask for the following */ | 160 | #define UFS_UID_MASK 0x00000060 /* mask for the following */ |
166 | #define UFS_UID_OLD 0x00000000 | 161 | #define UFS_UID_OLD 0x00000000 |
167 | #define UFS_UID_44BSD 0x00000020 | 162 | #define UFS_UID_44BSD 0x00000020 |
168 | #define UFS_UID_EFT 0x00000040 | 163 | #define UFS_UID_EFT 0x00000040 |
169 | /* superblock state encoding */ | 164 | /* superblock state encoding */ |
170 | #define UFS_ST_MASK 0x00000700 /* mask for the following */ | 165 | #define UFS_ST_MASK 0x00000700 /* mask for the following */ |
171 | #define UFS_ST_OLD 0x00000000 | 166 | #define UFS_ST_OLD 0x00000000 |
172 | #define UFS_ST_44BSD 0x00000100 | 167 | #define UFS_ST_44BSD 0x00000100 |
173 | #define UFS_ST_SUN 0x00000200 /* Solaris */ | 168 | #define UFS_ST_SUN 0x00000200 /* Solaris */ |
174 | #define UFS_ST_SUNOS 0x00000300 | 169 | #define UFS_ST_SUNOS 0x00000300 |
175 | #define UFS_ST_SUNx86 0x00000400 /* Solaris x86 */ | 170 | #define UFS_ST_SUNx86 0x00000400 /* Solaris x86 */ |
176 | /*cylinder group encoding */ | 171 | /*cylinder group encoding */ |
177 | #define UFS_CG_MASK 0x00003000 /* mask for the following */ | 172 | #define UFS_CG_MASK 0x00003000 /* mask for the following */ |
178 | #define UFS_CG_OLD 0x00000000 | 173 | #define UFS_CG_OLD 0x00000000 |
179 | #define UFS_CG_44BSD 0x00002000 | 174 | #define UFS_CG_44BSD 0x00002000 |
180 | #define UFS_CG_SUN 0x00001000 | 175 | #define UFS_CG_SUN 0x00001000 |
181 | /* filesystem type encoding */ | 176 | /* filesystem type encoding */ |
182 | #define UFS_TYPE_MASK 0x00010000 /* mask for the following */ | 177 | #define UFS_TYPE_MASK 0x00010000 /* mask for the following */ |
183 | #define UFS_TYPE_UFS1 0x00000000 | 178 | #define UFS_TYPE_UFS1 0x00000000 |
184 | #define UFS_TYPE_UFS2 0x00010000 | 179 | #define UFS_TYPE_UFS2 0x00010000 |
185 | 180 | ||
186 | 181 | ||
187 | /* fs_inodefmt options */ | 182 | /* fs_inodefmt options */ |
188 | #define UFS_42INODEFMT -1 | 183 | #define UFS_42INODEFMT -1 |
189 | #define UFS_44INODEFMT 2 | 184 | #define UFS_44INODEFMT 2 |
190 | 185 | ||
191 | /* mount options */ | ||
192 | #define UFS_MOUNT_ONERROR 0x0000000F | ||
193 | #define UFS_MOUNT_ONERROR_PANIC 0x00000001 | ||
194 | #define UFS_MOUNT_ONERROR_LOCK 0x00000002 | ||
195 | #define UFS_MOUNT_ONERROR_UMOUNT 0x00000004 | ||
196 | #define UFS_MOUNT_ONERROR_REPAIR 0x00000008 | ||
197 | |||
198 | #define UFS_MOUNT_UFSTYPE 0x0000FFF0 | ||
199 | #define UFS_MOUNT_UFSTYPE_OLD 0x00000010 | ||
200 | #define UFS_MOUNT_UFSTYPE_44BSD 0x00000020 | ||
201 | #define UFS_MOUNT_UFSTYPE_SUN 0x00000040 | ||
202 | #define UFS_MOUNT_UFSTYPE_NEXTSTEP 0x00000080 | ||
203 | #define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100 | ||
204 | #define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200 | ||
205 | #define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400 | ||
206 | #define UFS_MOUNT_UFSTYPE_HP 0x00000800 | ||
207 | #define UFS_MOUNT_UFSTYPE_UFS2 0x00001000 | ||
208 | #define UFS_MOUNT_UFSTYPE_SUNOS 0x00002000 | ||
209 | |||
210 | #define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt | ||
211 | #define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt | ||
212 | #define ufs_test_opt(o,opt) ((o) & UFS_MOUNT_##opt) | ||
213 | |||
214 | /* | 186 | /* |
215 | * MINFREE gives the minimum acceptable percentage of file system | 187 | * MINFREE gives the minimum acceptable percentage of file system |
216 | * blocks which may be free. If the freelist drops below this level | 188 | * blocks which may be free. If the freelist drops below this level |
217 | * only the superuser may continue to allocate blocks. This may | 189 | * only the superuser may continue to allocate blocks. This may |
218 | * be set to 0 if no reserve of free blocks is deemed necessary, | 190 | * be set to 0 if no reserve of free blocks is deemed necessary, |
219 | * however throughput drops by fifty percent if the file system | 191 | * however throughput drops by fifty percent if the file system |
220 | * is run at between 95% and 100% full; thus the minimum default | 192 | * is run at between 95% and 100% full; thus the minimum default |
221 | * value of fs_minfree is 5%. However, to get good clustering | 193 | * value of fs_minfree is 5%. However, to get good clustering |
222 | * performance, 10% is a better choice. hence we use 10% as our | 194 | * performance, 10% is a better choice. hence we use 10% as our |
223 | * default value. With 10% free space, fragmentation is not a | 195 | * default value. With 10% free space, fragmentation is not a |
224 | * problem, so we choose to optimize for time. | 196 | * problem, so we choose to optimize for time. |
225 | */ | 197 | */ |
226 | #define UFS_MINFREE 5 | 198 | #define UFS_MINFREE 5 |
227 | #define UFS_DEFAULTOPT UFS_OPTTIME | 199 | #define UFS_DEFAULTOPT UFS_OPTTIME |
228 | |||
229 | /* | ||
230 | * Debug code | ||
231 | */ | ||
232 | #ifdef CONFIG_UFS_DEBUG | ||
233 | # define UFSD(f, a...) { \ | ||
234 | printk ("UFSD (%s, %d): %s:", \ | ||
235 | __FILE__, __LINE__, __FUNCTION__); \ | ||
236 | printk (f, ## a); \ | ||
237 | } | ||
238 | #else | ||
239 | # define UFSD(f, a...) /**/ | ||
240 | #endif | ||
241 | 200 | ||
242 | /* | 201 | /* |
243 | * Turn file system block numbers into disk block addresses. | 202 | * Turn file system block numbers into disk block addresses. |
244 | * This maps file system blocks to device size blocks. | 203 | * This maps file system blocks to device size blocks. |
245 | */ | 204 | */ |
246 | #define ufs_fsbtodb(uspi, b) ((b) << (uspi)->s_fsbtodb) | 205 | #define ufs_fsbtodb(uspi, b) ((b) << (uspi)->s_fsbtodb) |
247 | #define ufs_dbtofsb(uspi, b) ((b) >> (uspi)->s_fsbtodb) | 206 | #define ufs_dbtofsb(uspi, b) ((b) >> (uspi)->s_fsbtodb) |
248 | 207 | ||
249 | /* | 208 | /* |
250 | * Cylinder group macros to locate things in cylinder groups. | 209 | * Cylinder group macros to locate things in cylinder groups. |
251 | * They calc file system addresses of cylinder group data structures. | 210 | * They calc file system addresses of cylinder group data structures. |
252 | */ | 211 | */ |
253 | #define ufs_cgbase(c) (uspi->s_fpg * (c)) | 212 | #define ufs_cgbase(c) (uspi->s_fpg * (c)) |
254 | #define ufs_cgstart(c) ((uspi)->fs_magic == UFS2_MAGIC ? ufs_cgbase(c) : \ | 213 | #define ufs_cgstart(c) ((uspi)->fs_magic == UFS2_MAGIC ? ufs_cgbase(c) : \ |
255 | (ufs_cgbase(c) + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))) | 214 | (ufs_cgbase(c) + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))) |
256 | #define ufs_cgsblock(c) (ufs_cgstart(c) + uspi->s_sblkno) /* super blk */ | 215 | #define ufs_cgsblock(c) (ufs_cgstart(c) + uspi->s_sblkno) /* super blk */ |
257 | #define ufs_cgcmin(c) (ufs_cgstart(c) + uspi->s_cblkno) /* cg block */ | 216 | #define ufs_cgcmin(c) (ufs_cgstart(c) + uspi->s_cblkno) /* cg block */ |
258 | #define ufs_cgimin(c) (ufs_cgstart(c) + uspi->s_iblkno) /* inode blk */ | 217 | #define ufs_cgimin(c) (ufs_cgstart(c) + uspi->s_iblkno) /* inode blk */ |
259 | #define ufs_cgdmin(c) (ufs_cgstart(c) + uspi->s_dblkno) /* 1st data */ | 218 | #define ufs_cgdmin(c) (ufs_cgstart(c) + uspi->s_dblkno) /* 1st data */ |
260 | 219 | ||
261 | /* | 220 | /* |
262 | * Macros for handling inode numbers: | 221 | * Macros for handling inode numbers: |
263 | * inode number to file system block offset. | 222 | * inode number to file system block offset. |
264 | * inode number to cylinder group number. | 223 | * inode number to cylinder group number. |
265 | * inode number to file system block address. | 224 | * inode number to file system block address. |
266 | */ | 225 | */ |
267 | #define ufs_inotocg(x) ((x) / uspi->s_ipg) | 226 | #define ufs_inotocg(x) ((x) / uspi->s_ipg) |
268 | #define ufs_inotocgoff(x) ((x) % uspi->s_ipg) | 227 | #define ufs_inotocgoff(x) ((x) % uspi->s_ipg) |
269 | #define ufs_inotofsba(x) (((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf) | 228 | #define ufs_inotofsba(x) (((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf) |
270 | #define ufs_inotofsbo(x) ((x) % uspi->s_inopf) | 229 | #define ufs_inotofsbo(x) ((x) % uspi->s_inopf) |
271 | 230 | ||
272 | /* | 231 | /* |
273 | * Compute the cylinder and rotational position of a cyl block addr. | 232 | * Compute the cylinder and rotational position of a cyl block addr. |
274 | */ | 233 | */ |
275 | #define ufs_cbtocylno(bno) \ | 234 | #define ufs_cbtocylno(bno) \ |
276 | ((bno) * uspi->s_nspf / uspi->s_spc) | 235 | ((bno) * uspi->s_nspf / uspi->s_spc) |
277 | #define ufs_cbtorpos(bno) \ | 236 | #define ufs_cbtorpos(bno) \ |
278 | ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \ | 237 | ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \ |
279 | * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \ | 238 | * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \ |
280 | % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \ | 239 | % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \ |
281 | * uspi->s_nrpos) / uspi->s_npsect) | 240 | * uspi->s_nrpos) / uspi->s_npsect) |
282 | 241 | ||
283 | /* | 242 | /* |
284 | * The following macros optimize certain frequently calculated | 243 | * The following macros optimize certain frequently calculated |
285 | * quantities by using shifts and masks in place of divisions | 244 | * quantities by using shifts and masks in place of divisions |
286 | * modulos and multiplications. | 245 | * modulos and multiplications. |
287 | */ | 246 | */ |
288 | #define ufs_blkoff(loc) ((loc) & uspi->s_qbmask) | 247 | #define ufs_blkoff(loc) ((loc) & uspi->s_qbmask) |
289 | #define ufs_fragoff(loc) ((loc) & uspi->s_qfmask) | 248 | #define ufs_fragoff(loc) ((loc) & uspi->s_qfmask) |
290 | #define ufs_lblktosize(blk) ((blk) << uspi->s_bshift) | 249 | #define ufs_lblktosize(blk) ((blk) << uspi->s_bshift) |
291 | #define ufs_lblkno(loc) ((loc) >> uspi->s_bshift) | 250 | #define ufs_lblkno(loc) ((loc) >> uspi->s_bshift) |
292 | #define ufs_numfrags(loc) ((loc) >> uspi->s_fshift) | 251 | #define ufs_numfrags(loc) ((loc) >> uspi->s_fshift) |
293 | #define ufs_blkroundup(size) (((size) + uspi->s_qbmask) & uspi->s_bmask) | 252 | #define ufs_blkroundup(size) (((size) + uspi->s_qbmask) & uspi->s_bmask) |
294 | #define ufs_fragroundup(size) (((size) + uspi->s_qfmask) & uspi->s_fmask) | 253 | #define ufs_fragroundup(size) (((size) + uspi->s_qfmask) & uspi->s_fmask) |
295 | #define ufs_fragstoblks(frags) ((frags) >> uspi->s_fpbshift) | 254 | #define ufs_fragstoblks(frags) ((frags) >> uspi->s_fpbshift) |
296 | #define ufs_blkstofrags(blks) ((blks) << uspi->s_fpbshift) | 255 | #define ufs_blkstofrags(blks) ((blks) << uspi->s_fpbshift) |
297 | #define ufs_fragnum(fsb) ((fsb) & uspi->s_fpbmask) | 256 | #define ufs_fragnum(fsb) ((fsb) & uspi->s_fpbmask) |
298 | #define ufs_blknum(fsb) ((fsb) & ~uspi->s_fpbmask) | 257 | #define ufs_blknum(fsb) ((fsb) & ~uspi->s_fpbmask) |
299 | 258 | ||
300 | #define UFS_MAXNAMLEN 255 | 259 | #define UFS_MAXNAMLEN 255 |
301 | #define UFS_MAXMNTLEN 512 | 260 | #define UFS_MAXMNTLEN 512 |
302 | #define UFS2_MAXMNTLEN 468 | 261 | #define UFS2_MAXMNTLEN 468 |
303 | #define UFS2_MAXVOLLEN 32 | 262 | #define UFS2_MAXVOLLEN 32 |
304 | #define UFS_MAXCSBUFS 31 | 263 | #define UFS_MAXCSBUFS 31 |
305 | #define UFS_LINK_MAX 32000 | 264 | #define UFS_LINK_MAX 32000 |
306 | /* | 265 | /* |
307 | #define UFS2_NOCSPTRS ((128 / sizeof(void *)) - 4) | 266 | #define UFS2_NOCSPTRS ((128 / sizeof(void *)) - 4) |
308 | */ | 267 | */ |
309 | #define UFS2_NOCSPTRS 28 | 268 | #define UFS2_NOCSPTRS 28 |
310 | 269 | ||
311 | /* | 270 | /* |
312 | * UFS_DIR_PAD defines the directory entries boundaries | 271 | * UFS_DIR_PAD defines the directory entries boundaries |
313 | * (must be a multiple of 4) | 272 | * (must be a multiple of 4) |
314 | */ | 273 | */ |
315 | #define UFS_DIR_PAD 4 | 274 | #define UFS_DIR_PAD 4 |
316 | #define UFS_DIR_ROUND (UFS_DIR_PAD - 1) | 275 | #define UFS_DIR_ROUND (UFS_DIR_PAD - 1) |
317 | #define UFS_DIR_REC_LEN(name_len) (((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND) | 276 | #define UFS_DIR_REC_LEN(name_len) (((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND) |
318 | 277 | ||
319 | struct ufs_timeval { | 278 | struct ufs_timeval { |
320 | __fs32 tv_sec; | 279 | __fs32 tv_sec; |
321 | __fs32 tv_usec; | 280 | __fs32 tv_usec; |
322 | }; | 281 | }; |
323 | 282 | ||
324 | struct ufs_dir_entry { | 283 | struct ufs_dir_entry { |
325 | __fs32 d_ino; /* inode number of this entry */ | 284 | __fs32 d_ino; /* inode number of this entry */ |
326 | __fs16 d_reclen; /* length of this entry */ | 285 | __fs16 d_reclen; /* length of this entry */ |
327 | union { | 286 | union { |
328 | __fs16 d_namlen; /* actual length of d_name */ | 287 | __fs16 d_namlen; /* actual length of d_name */ |
329 | struct { | 288 | struct { |
330 | __u8 d_type; /* file type */ | 289 | __u8 d_type; /* file type */ |
331 | __u8 d_namlen; /* length of string in d_name */ | 290 | __u8 d_namlen; /* length of string in d_name */ |
332 | } d_44; | 291 | } d_44; |
333 | } d_u; | 292 | } d_u; |
334 | __u8 d_name[UFS_MAXNAMLEN + 1]; /* file name */ | 293 | __u8 d_name[UFS_MAXNAMLEN + 1]; /* file name */ |
335 | }; | 294 | }; |
336 | 295 | ||
337 | struct ufs_csum { | 296 | struct ufs_csum { |
338 | __fs32 cs_ndir; /* number of directories */ | 297 | __fs32 cs_ndir; /* number of directories */ |
339 | __fs32 cs_nbfree; /* number of free blocks */ | 298 | __fs32 cs_nbfree; /* number of free blocks */ |
340 | __fs32 cs_nifree; /* number of free inodes */ | 299 | __fs32 cs_nifree; /* number of free inodes */ |
341 | __fs32 cs_nffree; /* number of free frags */ | 300 | __fs32 cs_nffree; /* number of free frags */ |
342 | }; | 301 | }; |
343 | struct ufs2_csum_total { | 302 | struct ufs2_csum_total { |
344 | __fs64 cs_ndir; /* number of directories */ | 303 | __fs64 cs_ndir; /* number of directories */ |
345 | __fs64 cs_nbfree; /* number of free blocks */ | 304 | __fs64 cs_nbfree; /* number of free blocks */ |
346 | __fs64 cs_nifree; /* number of free inodes */ | 305 | __fs64 cs_nifree; /* number of free inodes */ |
347 | __fs64 cs_nffree; /* number of free frags */ | 306 | __fs64 cs_nffree; /* number of free frags */ |
348 | __fs64 cs_numclusters; /* number of free clusters */ | 307 | __fs64 cs_numclusters; /* number of free clusters */ |
349 | __fs64 cs_spare[3]; /* future expansion */ | 308 | __fs64 cs_spare[3]; /* future expansion */ |
350 | }; | 309 | }; |
351 | 310 | ||
352 | struct ufs_csum_core { | 311 | struct ufs_csum_core { |
353 | __u64 cs_ndir; /* number of directories */ | 312 | __u64 cs_ndir; /* number of directories */ |
354 | __u64 cs_nbfree; /* number of free blocks */ | 313 | __u64 cs_nbfree; /* number of free blocks */ |
355 | __u64 cs_nifree; /* number of free inodes */ | 314 | __u64 cs_nifree; /* number of free inodes */ |
356 | __u64 cs_nffree; /* number of free frags */ | 315 | __u64 cs_nffree; /* number of free frags */ |
357 | __u64 cs_numclusters; /* number of free clusters */ | 316 | __u64 cs_numclusters; /* number of free clusters */ |
358 | }; | 317 | }; |
359 | 318 | ||
360 | /* | 319 | /* |
361 | * File system flags | 320 | * File system flags |
362 | */ | 321 | */ |
363 | #define UFS_UNCLEAN 0x01 /* file system not clean at mount (unused) */ | 322 | #define UFS_UNCLEAN 0x01 /* file system not clean at mount (unused) */ |
364 | #define UFS_DOSOFTDEP 0x02 /* file system using soft dependencies */ | 323 | #define UFS_DOSOFTDEP 0x02 /* file system using soft dependencies */ |
365 | #define UFS_NEEDSFSCK 0x04 /* needs sync fsck (FreeBSD compat, unused) */ | 324 | #define UFS_NEEDSFSCK 0x04 /* needs sync fsck (FreeBSD compat, unused) */ |
366 | #define UFS_INDEXDIRS 0x08 /* kernel supports indexed directories */ | 325 | #define UFS_INDEXDIRS 0x08 /* kernel supports indexed directories */ |
367 | #define UFS_ACLS 0x10 /* file system has ACLs enabled */ | 326 | #define UFS_ACLS 0x10 /* file system has ACLs enabled */ |
368 | #define UFS_MULTILABEL 0x20 /* file system is MAC multi-label */ | 327 | #define UFS_MULTILABEL 0x20 /* file system is MAC multi-label */ |
369 | #define UFS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ | 328 | #define UFS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ |
370 | 329 | ||
371 | #if 0 | 330 | #if 0 |
372 | /* | 331 | /* |
373 | * This is the actual superblock, as it is laid out on the disk. | 332 | * This is the actual superblock, as it is laid out on the disk. |
374 | * Do NOT use this structure, because of sizeof(ufs_super_block) > 512 and | 333 | * Do NOT use this structure, because of sizeof(ufs_super_block) > 512 and |
375 | * it may occupy several blocks, use | 334 | * it may occupy several blocks, use |
376 | * struct ufs_super_block_(first,second,third) instead. | 335 | * struct ufs_super_block_(first,second,third) instead. |
377 | */ | 336 | */ |
378 | struct ufs_super_block { | 337 | struct ufs_super_block { |
379 | union { | 338 | union { |
380 | struct { | 339 | struct { |
381 | __fs32 fs_link; /* UNUSED */ | 340 | __fs32 fs_link; /* UNUSED */ |
382 | } fs_42; | 341 | } fs_42; |
383 | struct { | 342 | struct { |
384 | __fs32 fs_state; /* file system state flag */ | 343 | __fs32 fs_state; /* file system state flag */ |
385 | } fs_sun; | 344 | } fs_sun; |
386 | } fs_u0; | 345 | } fs_u0; |
387 | __fs32 fs_rlink; /* UNUSED */ | 346 | __fs32 fs_rlink; /* UNUSED */ |
388 | __fs32 fs_sblkno; /* addr of super-block in filesys */ | 347 | __fs32 fs_sblkno; /* addr of super-block in filesys */ |
389 | __fs32 fs_cblkno; /* offset of cyl-block in filesys */ | 348 | __fs32 fs_cblkno; /* offset of cyl-block in filesys */ |
390 | __fs32 fs_iblkno; /* offset of inode-blocks in filesys */ | 349 | __fs32 fs_iblkno; /* offset of inode-blocks in filesys */ |
391 | __fs32 fs_dblkno; /* offset of first data after cg */ | 350 | __fs32 fs_dblkno; /* offset of first data after cg */ |
392 | __fs32 fs_cgoffset; /* cylinder group offset in cylinder */ | 351 | __fs32 fs_cgoffset; /* cylinder group offset in cylinder */ |
393 | __fs32 fs_cgmask; /* used to calc mod fs_ntrak */ | 352 | __fs32 fs_cgmask; /* used to calc mod fs_ntrak */ |
394 | __fs32 fs_time; /* last time written -- time_t */ | 353 | __fs32 fs_time; /* last time written -- time_t */ |
395 | __fs32 fs_size; /* number of blocks in fs */ | 354 | __fs32 fs_size; /* number of blocks in fs */ |
396 | __fs32 fs_dsize; /* number of data blocks in fs */ | 355 | __fs32 fs_dsize; /* number of data blocks in fs */ |
397 | __fs32 fs_ncg; /* number of cylinder groups */ | 356 | __fs32 fs_ncg; /* number of cylinder groups */ |
398 | __fs32 fs_bsize; /* size of basic blocks in fs */ | 357 | __fs32 fs_bsize; /* size of basic blocks in fs */ |
399 | __fs32 fs_fsize; /* size of frag blocks in fs */ | 358 | __fs32 fs_fsize; /* size of frag blocks in fs */ |
400 | __fs32 fs_frag; /* number of frags in a block in fs */ | 359 | __fs32 fs_frag; /* number of frags in a block in fs */ |
401 | /* these are configuration parameters */ | 360 | /* these are configuration parameters */ |
402 | __fs32 fs_minfree; /* minimum percentage of free blocks */ | 361 | __fs32 fs_minfree; /* minimum percentage of free blocks */ |
403 | __fs32 fs_rotdelay; /* num of ms for optimal next block */ | 362 | __fs32 fs_rotdelay; /* num of ms for optimal next block */ |
404 | __fs32 fs_rps; /* disk revolutions per second */ | 363 | __fs32 fs_rps; /* disk revolutions per second */ |
405 | /* these fields can be computed from the others */ | 364 | /* these fields can be computed from the others */ |
406 | __fs32 fs_bmask; /* ``blkoff'' calc of blk offsets */ | 365 | __fs32 fs_bmask; /* ``blkoff'' calc of blk offsets */ |
407 | __fs32 fs_fmask; /* ``fragoff'' calc of frag offsets */ | 366 | __fs32 fs_fmask; /* ``fragoff'' calc of frag offsets */ |
408 | __fs32 fs_bshift; /* ``lblkno'' calc of logical blkno */ | 367 | __fs32 fs_bshift; /* ``lblkno'' calc of logical blkno */ |
409 | __fs32 fs_fshift; /* ``numfrags'' calc number of frags */ | 368 | __fs32 fs_fshift; /* ``numfrags'' calc number of frags */ |
410 | /* these are configuration parameters */ | 369 | /* these are configuration parameters */ |
411 | __fs32 fs_maxcontig; /* max number of contiguous blks */ | 370 | __fs32 fs_maxcontig; /* max number of contiguous blks */ |
412 | __fs32 fs_maxbpg; /* max number of blks per cyl group */ | 371 | __fs32 fs_maxbpg; /* max number of blks per cyl group */ |
413 | /* these fields can be computed from the others */ | 372 | /* these fields can be computed from the others */ |
414 | __fs32 fs_fragshift; /* block to frag shift */ | 373 | __fs32 fs_fragshift; /* block to frag shift */ |
415 | __fs32 fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ | 374 | __fs32 fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ |
416 | __fs32 fs_sbsize; /* actual size of super block */ | 375 | __fs32 fs_sbsize; /* actual size of super block */ |
417 | __fs32 fs_csmask; /* csum block offset */ | 376 | __fs32 fs_csmask; /* csum block offset */ |
418 | __fs32 fs_csshift; /* csum block number */ | 377 | __fs32 fs_csshift; /* csum block number */ |
419 | __fs32 fs_nindir; /* value of NINDIR */ | 378 | __fs32 fs_nindir; /* value of NINDIR */ |
420 | __fs32 fs_inopb; /* value of INOPB */ | 379 | __fs32 fs_inopb; /* value of INOPB */ |
421 | __fs32 fs_nspf; /* value of NSPF */ | 380 | __fs32 fs_nspf; /* value of NSPF */ |
422 | /* yet another configuration parameter */ | 381 | /* yet another configuration parameter */ |
423 | __fs32 fs_optim; /* optimization preference, see below */ | 382 | __fs32 fs_optim; /* optimization preference, see below */ |
424 | /* these fields are derived from the hardware */ | 383 | /* these fields are derived from the hardware */ |
425 | union { | 384 | union { |
426 | struct { | 385 | struct { |
427 | __fs32 fs_npsect; /* # sectors/track including spares */ | 386 | __fs32 fs_npsect; /* # sectors/track including spares */ |
428 | } fs_sun; | 387 | } fs_sun; |
429 | struct { | 388 | struct { |
430 | __fs32 fs_state; /* file system state time stamp */ | 389 | __fs32 fs_state; /* file system state time stamp */ |
431 | } fs_sunx86; | 390 | } fs_sunx86; |
432 | } fs_u1; | 391 | } fs_u1; |
433 | __fs32 fs_interleave; /* hardware sector interleave */ | 392 | __fs32 fs_interleave; /* hardware sector interleave */ |
434 | __fs32 fs_trackskew; /* sector 0 skew, per track */ | 393 | __fs32 fs_trackskew; /* sector 0 skew, per track */ |
435 | /* a unique id for this filesystem (currently unused and unmaintained) */ | 394 | /* a unique id for this filesystem (currently unused and unmaintained) */ |
436 | /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ | 395 | /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ |
437 | /* Neither of those fields is used in the Tahoe code right now but */ | 396 | /* Neither of those fields is used in the Tahoe code right now but */ |
438 | /* there could be problems if they are. */ | 397 | /* there could be problems if they are. */ |
439 | __fs32 fs_id[2]; /* file system id */ | 398 | __fs32 fs_id[2]; /* file system id */ |
440 | /* sizes determined by number of cylinder groups and their sizes */ | 399 | /* sizes determined by number of cylinder groups and their sizes */ |
441 | __fs32 fs_csaddr; /* blk addr of cyl grp summary area */ | 400 | __fs32 fs_csaddr; /* blk addr of cyl grp summary area */ |
442 | __fs32 fs_cssize; /* size of cyl grp summary area */ | 401 | __fs32 fs_cssize; /* size of cyl grp summary area */ |
443 | __fs32 fs_cgsize; /* cylinder group size */ | 402 | __fs32 fs_cgsize; /* cylinder group size */ |
444 | /* these fields are derived from the hardware */ | 403 | /* these fields are derived from the hardware */ |
445 | __fs32 fs_ntrak; /* tracks per cylinder */ | 404 | __fs32 fs_ntrak; /* tracks per cylinder */ |
446 | __fs32 fs_nsect; /* sectors per track */ | 405 | __fs32 fs_nsect; /* sectors per track */ |
447 | __fs32 fs_spc; /* sectors per cylinder */ | 406 | __fs32 fs_spc; /* sectors per cylinder */ |
448 | /* this comes from the disk driver partitioning */ | 407 | /* this comes from the disk driver partitioning */ |
449 | __fs32 fs_ncyl; /* cylinders in file system */ | 408 | __fs32 fs_ncyl; /* cylinders in file system */ |
450 | /* these fields can be computed from the others */ | 409 | /* these fields can be computed from the others */ |
451 | __fs32 fs_cpg; /* cylinders per group */ | 410 | __fs32 fs_cpg; /* cylinders per group */ |
452 | __fs32 fs_ipg; /* inodes per cylinder group */ | 411 | __fs32 fs_ipg; /* inodes per cylinder group */ |
453 | __fs32 fs_fpg; /* blocks per group * fs_frag */ | 412 | __fs32 fs_fpg; /* blocks per group * fs_frag */ |
454 | /* this data must be re-computed after crashes */ | 413 | /* this data must be re-computed after crashes */ |
455 | struct ufs_csum fs_cstotal; /* cylinder summary information */ | 414 | struct ufs_csum fs_cstotal; /* cylinder summary information */ |
456 | /* these fields are cleared at mount time */ | 415 | /* these fields are cleared at mount time */ |
457 | __s8 fs_fmod; /* super block modified flag */ | 416 | __s8 fs_fmod; /* super block modified flag */ |
458 | __s8 fs_clean; /* file system is clean flag */ | 417 | __s8 fs_clean; /* file system is clean flag */ |
459 | __s8 fs_ronly; /* mounted read-only flag */ | 418 | __s8 fs_ronly; /* mounted read-only flag */ |
460 | __s8 fs_flags; | 419 | __s8 fs_flags; |
461 | union { | 420 | union { |
462 | struct { | 421 | struct { |
463 | __s8 fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */ | 422 | __s8 fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */ |
464 | __fs32 fs_cgrotor; /* last cg searched */ | 423 | __fs32 fs_cgrotor; /* last cg searched */ |
465 | __fs32 fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */ | 424 | __fs32 fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */ |
466 | __fs32 fs_maxcluster; | 425 | __fs32 fs_maxcluster; |
467 | __fs32 fs_cpc; /* cyl per cycle in postbl */ | 426 | __fs32 fs_cpc; /* cyl per cycle in postbl */ |
468 | __fs16 fs_opostbl[16][8]; /* old rotation block list head */ | 427 | __fs16 fs_opostbl[16][8]; /* old rotation block list head */ |
469 | } fs_u1; | 428 | } fs_u1; |
470 | struct { | 429 | struct { |
471 | __s8 fs_fsmnt[UFS2_MAXMNTLEN]; /* name mounted on */ | 430 | __s8 fs_fsmnt[UFS2_MAXMNTLEN]; /* name mounted on */ |
472 | __u8 fs_volname[UFS2_MAXVOLLEN]; /* volume name */ | 431 | __u8 fs_volname[UFS2_MAXVOLLEN]; /* volume name */ |
473 | __fs64 fs_swuid; /* system-wide uid */ | 432 | __fs64 fs_swuid; /* system-wide uid */ |
474 | __fs32 fs_pad; /* due to alignment of fs_swuid */ | 433 | __fs32 fs_pad; /* due to alignment of fs_swuid */ |
475 | __fs32 fs_cgrotor; /* last cg searched */ | 434 | __fs32 fs_cgrotor; /* last cg searched */ |
476 | __fs32 fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */ | 435 | __fs32 fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */ |
477 | __fs32 fs_contigdirs;/*# of contiguously allocated dirs */ | 436 | __fs32 fs_contigdirs;/*# of contiguously allocated dirs */ |
478 | __fs32 fs_csp; /* cg summary info buffer for fs_cs */ | 437 | __fs32 fs_csp; /* cg summary info buffer for fs_cs */ |
479 | __fs32 fs_maxcluster; | 438 | __fs32 fs_maxcluster; |
480 | __fs32 fs_active;/* used by snapshots to track fs */ | 439 | __fs32 fs_active;/* used by snapshots to track fs */ |
481 | __fs32 fs_old_cpc; /* cyl per cycle in postbl */ | 440 | __fs32 fs_old_cpc; /* cyl per cycle in postbl */ |
482 | __fs32 fs_maxbsize;/*maximum blocking factor permitted */ | 441 | __fs32 fs_maxbsize;/*maximum blocking factor permitted */ |
483 | __fs64 fs_sparecon64[17];/*old rotation block list head */ | 442 | __fs64 fs_sparecon64[17];/*old rotation block list head */ |
484 | __fs64 fs_sblockloc; /* byte offset of standard superblock */ | 443 | __fs64 fs_sblockloc; /* byte offset of standard superblock */ |
485 | struct ufs2_csum_total fs_cstotal;/*cylinder summary information*/ | 444 | struct ufs2_csum_total fs_cstotal;/*cylinder summary information*/ |
486 | struct ufs_timeval fs_time; /* last time written */ | 445 | struct ufs_timeval fs_time; /* last time written */ |
487 | __fs64 fs_size; /* number of blocks in fs */ | 446 | __fs64 fs_size; /* number of blocks in fs */ |
488 | __fs64 fs_dsize; /* number of data blocks in fs */ | 447 | __fs64 fs_dsize; /* number of data blocks in fs */ |
489 | __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ | 448 | __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ |
490 | __fs64 fs_pendingblocks;/* blocks in process of being freed */ | 449 | __fs64 fs_pendingblocks;/* blocks in process of being freed */ |
491 | __fs32 fs_pendinginodes;/*inodes in process of being freed */ | 450 | __fs32 fs_pendinginodes;/*inodes in process of being freed */ |
492 | } fs_u2; | 451 | } fs_u2; |
493 | } fs_u11; | 452 | } fs_u11; |
494 | union { | 453 | union { |
495 | struct { | 454 | struct { |
496 | __fs32 fs_sparecon[53];/* reserved for future constants */ | 455 | __fs32 fs_sparecon[53];/* reserved for future constants */ |
497 | __fs32 fs_reclaim; | 456 | __fs32 fs_reclaim; |
498 | __fs32 fs_sparecon2[1]; | 457 | __fs32 fs_sparecon2[1]; |
499 | __fs32 fs_state; /* file system state time stamp */ | 458 | __fs32 fs_state; /* file system state time stamp */ |
500 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 459 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
501 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 460 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
502 | } fs_sun; | 461 | } fs_sun; |
503 | struct { | 462 | struct { |
504 | __fs32 fs_sparecon[53];/* reserved for future constants */ | 463 | __fs32 fs_sparecon[53];/* reserved for future constants */ |
505 | __fs32 fs_reclaim; | 464 | __fs32 fs_reclaim; |
506 | __fs32 fs_sparecon2[1]; | 465 | __fs32 fs_sparecon2[1]; |
507 | __fs32 fs_npsect; /* # sectors/track including spares */ | 466 | __fs32 fs_npsect; /* # sectors/track including spares */ |
508 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 467 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
509 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 468 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
510 | } fs_sunx86; | 469 | } fs_sunx86; |
511 | struct { | 470 | struct { |
512 | __fs32 fs_sparecon[50];/* reserved for future constants */ | 471 | __fs32 fs_sparecon[50];/* reserved for future constants */ |
513 | __fs32 fs_contigsumsize;/* size of cluster summary array */ | 472 | __fs32 fs_contigsumsize;/* size of cluster summary array */ |
514 | __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ | 473 | __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ |
515 | __fs32 fs_inodefmt; /* format of on-disk inodes */ | 474 | __fs32 fs_inodefmt; /* format of on-disk inodes */ |
516 | __fs32 fs_maxfilesize[2]; /* max representable file size */ | 475 | __fs32 fs_maxfilesize[2]; /* max representable file size */ |
517 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 476 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
518 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 477 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
519 | __fs32 fs_state; /* file system state time stamp */ | 478 | __fs32 fs_state; /* file system state time stamp */ |
520 | } fs_44; | 479 | } fs_44; |
521 | } fs_u2; | 480 | } fs_u2; |
522 | __fs32 fs_postblformat; /* format of positional layout tables */ | 481 | __fs32 fs_postblformat; /* format of positional layout tables */ |
523 | __fs32 fs_nrpos; /* number of rotational positions */ | 482 | __fs32 fs_nrpos; /* number of rotational positions */ |
524 | __fs32 fs_postbloff; /* (__s16) rotation block list head */ | 483 | __fs32 fs_postbloff; /* (__s16) rotation block list head */ |
525 | __fs32 fs_rotbloff; /* (__u8) blocks for each rotation */ | 484 | __fs32 fs_rotbloff; /* (__u8) blocks for each rotation */ |
526 | __fs32 fs_magic; /* magic number */ | 485 | __fs32 fs_magic; /* magic number */ |
527 | __u8 fs_space[1]; /* list of blocks for each rotation */ | 486 | __u8 fs_space[1]; /* list of blocks for each rotation */ |
528 | }; | 487 | }; |
529 | #endif/*struct ufs_super_block*/ | 488 | #endif/*struct ufs_super_block*/ |
530 | 489 | ||
531 | /* | 490 | /* |
532 | * Preference for optimization. | 491 | * Preference for optimization. |
533 | */ | 492 | */ |
534 | #define UFS_OPTTIME 0 /* minimize allocation time */ | 493 | #define UFS_OPTTIME 0 /* minimize allocation time */ |
535 | #define UFS_OPTSPACE 1 /* minimize disk fragmentation */ | 494 | #define UFS_OPTSPACE 1 /* minimize disk fragmentation */ |
536 | 495 | ||
537 | /* | 496 | /* |
538 | * Rotational layout table format types | 497 | * Rotational layout table format types |
539 | */ | 498 | */ |
540 | #define UFS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ | 499 | #define UFS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ |
541 | #define UFS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ | 500 | #define UFS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ |
542 | 501 | ||
543 | /* | 502 | /* |
544 | * Convert cylinder group to base address of its global summary info. | 503 | * Convert cylinder group to base address of its global summary info. |
545 | */ | 504 | */ |
546 | #define fs_cs(indx) s_csp[(indx)] | 505 | #define fs_cs(indx) s_csp[(indx)] |
547 | 506 | ||
548 | /* | 507 | /* |
549 | * Cylinder group block for a file system. | 508 | * Cylinder group block for a file system. |
550 | * | 509 | * |
551 | * Writable fields in the cylinder group are protected by the associated | 510 | * Writable fields in the cylinder group are protected by the associated |
552 | * super block lock fs->fs_lock. | 511 | * super block lock fs->fs_lock. |
553 | */ | 512 | */ |
554 | #define CG_MAGIC 0x090255 | 513 | #define CG_MAGIC 0x090255 |
555 | #define ufs_cg_chkmagic(sb, ucg) \ | 514 | #define ufs_cg_chkmagic(sb, ucg) \ |
556 | (fs32_to_cpu((sb), (ucg)->cg_magic) == CG_MAGIC) | 515 | (fs32_to_cpu((sb), (ucg)->cg_magic) == CG_MAGIC) |
557 | /* | 516 | /* |
558 | * Macros for access to old cylinder group array structures | 517 | * Macros for access to old cylinder group array structures |
559 | */ | 518 | */ |
560 | #define ufs_ocg_blktot(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_btot) | 519 | #define ufs_ocg_blktot(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_btot) |
561 | #define ufs_ocg_blks(sb, ucg, cylno) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_b[cylno]) | 520 | #define ufs_ocg_blks(sb, ucg, cylno) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_b[cylno]) |
562 | #define ufs_ocg_inosused(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_iused) | 521 | #define ufs_ocg_inosused(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_iused) |
563 | #define ufs_ocg_blksfree(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_free) | 522 | #define ufs_ocg_blksfree(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_free) |
564 | #define ufs_ocg_chkmagic(sb, ucg) \ | 523 | #define ufs_ocg_chkmagic(sb, ucg) \ |
565 | (fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_magic) == CG_MAGIC) | 524 | (fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_magic) == CG_MAGIC) |
566 | 525 | ||
567 | /* | 526 | /* |
568 | * size of this structure is 172 B | 527 | * size of this structure is 172 B |
569 | */ | 528 | */ |
570 | struct ufs_cylinder_group { | 529 | struct ufs_cylinder_group { |
571 | __fs32 cg_link; /* linked list of cyl groups */ | 530 | __fs32 cg_link; /* linked list of cyl groups */ |
572 | __fs32 cg_magic; /* magic number */ | 531 | __fs32 cg_magic; /* magic number */ |
573 | __fs32 cg_time; /* time last written */ | 532 | __fs32 cg_time; /* time last written */ |
574 | __fs32 cg_cgx; /* we are the cgx'th cylinder group */ | 533 | __fs32 cg_cgx; /* we are the cgx'th cylinder group */ |
575 | __fs16 cg_ncyl; /* number of cyl's this cg */ | 534 | __fs16 cg_ncyl; /* number of cyl's this cg */ |
576 | __fs16 cg_niblk; /* number of inode blocks this cg */ | 535 | __fs16 cg_niblk; /* number of inode blocks this cg */ |
577 | __fs32 cg_ndblk; /* number of data blocks this cg */ | 536 | __fs32 cg_ndblk; /* number of data blocks this cg */ |
578 | struct ufs_csum cg_cs; /* cylinder summary information */ | 537 | struct ufs_csum cg_cs; /* cylinder summary information */ |
579 | __fs32 cg_rotor; /* position of last used block */ | 538 | __fs32 cg_rotor; /* position of last used block */ |
580 | __fs32 cg_frotor; /* position of last used frag */ | 539 | __fs32 cg_frotor; /* position of last used frag */ |
581 | __fs32 cg_irotor; /* position of last used inode */ | 540 | __fs32 cg_irotor; /* position of last used inode */ |
582 | __fs32 cg_frsum[UFS_MAXFRAG]; /* counts of available frags */ | 541 | __fs32 cg_frsum[UFS_MAXFRAG]; /* counts of available frags */ |
583 | __fs32 cg_btotoff; /* (__u32) block totals per cylinder */ | 542 | __fs32 cg_btotoff; /* (__u32) block totals per cylinder */ |
584 | __fs32 cg_boff; /* (short) free block positions */ | 543 | __fs32 cg_boff; /* (short) free block positions */ |
585 | __fs32 cg_iusedoff; /* (char) used inode map */ | 544 | __fs32 cg_iusedoff; /* (char) used inode map */ |
586 | __fs32 cg_freeoff; /* (u_char) free block map */ | 545 | __fs32 cg_freeoff; /* (u_char) free block map */ |
587 | __fs32 cg_nextfreeoff; /* (u_char) next available space */ | 546 | __fs32 cg_nextfreeoff; /* (u_char) next available space */ |
588 | union { | 547 | union { |
589 | struct { | 548 | struct { |
590 | __fs32 cg_clustersumoff; /* (u_int32) counts of avail clusters */ | 549 | __fs32 cg_clustersumoff; /* (u_int32) counts of avail clusters */ |
591 | __fs32 cg_clusteroff; /* (u_int8) free cluster map */ | 550 | __fs32 cg_clusteroff; /* (u_int8) free cluster map */ |
592 | __fs32 cg_nclusterblks; /* number of clusters this cg */ | 551 | __fs32 cg_nclusterblks; /* number of clusters this cg */ |
593 | __fs32 cg_sparecon[13]; /* reserved for future use */ | 552 | __fs32 cg_sparecon[13]; /* reserved for future use */ |
594 | } cg_44; | 553 | } cg_44; |
595 | struct { | 554 | struct { |
596 | __fs32 cg_clustersumoff;/* (u_int32) counts of avail clusters */ | 555 | __fs32 cg_clustersumoff;/* (u_int32) counts of avail clusters */ |
597 | __fs32 cg_clusteroff; /* (u_int8) free cluster map */ | 556 | __fs32 cg_clusteroff; /* (u_int8) free cluster map */ |
598 | __fs32 cg_nclusterblks;/* number of clusters this cg */ | 557 | __fs32 cg_nclusterblks;/* number of clusters this cg */ |
599 | __fs32 cg_niblk; /* number of inode blocks this cg */ | 558 | __fs32 cg_niblk; /* number of inode blocks this cg */ |
600 | __fs32 cg_initediblk; /* last initialized inode */ | 559 | __fs32 cg_initediblk; /* last initialized inode */ |
601 | __fs32 cg_sparecon32[3];/* reserved for future use */ | 560 | __fs32 cg_sparecon32[3];/* reserved for future use */ |
602 | __fs64 cg_time; /* time last written */ | 561 | __fs64 cg_time; /* time last written */ |
603 | __fs64 cg_sparecon[3]; /* reserved for future use */ | 562 | __fs64 cg_sparecon[3]; /* reserved for future use */ |
604 | } cg_u2; | 563 | } cg_u2; |
605 | __fs32 cg_sparecon[16]; /* reserved for future use */ | 564 | __fs32 cg_sparecon[16]; /* reserved for future use */ |
606 | } cg_u; | 565 | } cg_u; |
607 | __u8 cg_space[1]; /* space for cylinder group maps */ | 566 | __u8 cg_space[1]; /* space for cylinder group maps */ |
608 | /* actually longer */ | 567 | /* actually longer */ |
609 | }; | 568 | }; |
610 | 569 | ||
611 | /* Historic Cylinder group info */ | 570 | /* Historic Cylinder group info */ |
612 | struct ufs_old_cylinder_group { | 571 | struct ufs_old_cylinder_group { |
613 | __fs32 cg_link; /* linked list of cyl groups */ | 572 | __fs32 cg_link; /* linked list of cyl groups */ |
614 | __fs32 cg_rlink; /* for incore cyl groups */ | 573 | __fs32 cg_rlink; /* for incore cyl groups */ |
615 | __fs32 cg_time; /* time last written */ | 574 | __fs32 cg_time; /* time last written */ |
616 | __fs32 cg_cgx; /* we are the cgx'th cylinder group */ | 575 | __fs32 cg_cgx; /* we are the cgx'th cylinder group */ |
617 | __fs16 cg_ncyl; /* number of cyl's this cg */ | 576 | __fs16 cg_ncyl; /* number of cyl's this cg */ |
618 | __fs16 cg_niblk; /* number of inode blocks this cg */ | 577 | __fs16 cg_niblk; /* number of inode blocks this cg */ |
619 | __fs32 cg_ndblk; /* number of data blocks this cg */ | 578 | __fs32 cg_ndblk; /* number of data blocks this cg */ |
620 | struct ufs_csum cg_cs; /* cylinder summary information */ | 579 | struct ufs_csum cg_cs; /* cylinder summary information */ |
621 | __fs32 cg_rotor; /* position of last used block */ | 580 | __fs32 cg_rotor; /* position of last used block */ |
622 | __fs32 cg_frotor; /* position of last used frag */ | 581 | __fs32 cg_frotor; /* position of last used frag */ |
623 | __fs32 cg_irotor; /* position of last used inode */ | 582 | __fs32 cg_irotor; /* position of last used inode */ |
624 | __fs32 cg_frsum[8]; /* counts of available frags */ | 583 | __fs32 cg_frsum[8]; /* counts of available frags */ |
625 | __fs32 cg_btot[32]; /* block totals per cylinder */ | 584 | __fs32 cg_btot[32]; /* block totals per cylinder */ |
626 | __fs16 cg_b[32][8]; /* positions of free blocks */ | 585 | __fs16 cg_b[32][8]; /* positions of free blocks */ |
627 | __u8 cg_iused[256]; /* used inode map */ | 586 | __u8 cg_iused[256]; /* used inode map */ |
628 | __fs32 cg_magic; /* magic number */ | 587 | __fs32 cg_magic; /* magic number */ |
629 | __u8 cg_free[1]; /* free block map */ | 588 | __u8 cg_free[1]; /* free block map */ |
630 | /* actually longer */ | 589 | /* actually longer */ |
631 | }; | 590 | }; |
632 | 591 | ||
633 | /* | 592 | /* |
634 | * structure of an on-disk inode | 593 | * structure of an on-disk inode |
635 | */ | 594 | */ |
636 | struct ufs_inode { | 595 | struct ufs_inode { |
637 | __fs16 ui_mode; /* 0x0 */ | 596 | __fs16 ui_mode; /* 0x0 */ |
638 | __fs16 ui_nlink; /* 0x2 */ | 597 | __fs16 ui_nlink; /* 0x2 */ |
639 | union { | 598 | union { |
640 | struct { | 599 | struct { |
641 | __fs16 ui_suid; /* 0x4 */ | 600 | __fs16 ui_suid; /* 0x4 */ |
642 | __fs16 ui_sgid; /* 0x6 */ | 601 | __fs16 ui_sgid; /* 0x6 */ |
643 | } oldids; | 602 | } oldids; |
644 | __fs32 ui_inumber; /* 0x4 lsf: inode number */ | 603 | __fs32 ui_inumber; /* 0x4 lsf: inode number */ |
645 | __fs32 ui_author; /* 0x4 GNU HURD: author */ | 604 | __fs32 ui_author; /* 0x4 GNU HURD: author */ |
646 | } ui_u1; | 605 | } ui_u1; |
647 | __fs64 ui_size; /* 0x8 */ | 606 | __fs64 ui_size; /* 0x8 */ |
648 | struct ufs_timeval ui_atime; /* 0x10 access */ | 607 | struct ufs_timeval ui_atime; /* 0x10 access */ |
649 | struct ufs_timeval ui_mtime; /* 0x18 modification */ | 608 | struct ufs_timeval ui_mtime; /* 0x18 modification */ |
650 | struct ufs_timeval ui_ctime; /* 0x20 creation */ | 609 | struct ufs_timeval ui_ctime; /* 0x20 creation */ |
651 | union { | 610 | union { |
652 | struct { | 611 | struct { |
653 | __fs32 ui_db[UFS_NDADDR];/* 0x28 data blocks */ | 612 | __fs32 ui_db[UFS_NDADDR];/* 0x28 data blocks */ |
654 | __fs32 ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */ | 613 | __fs32 ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */ |
655 | } ui_addr; | 614 | } ui_addr; |
656 | __u8 ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ | 615 | __u8 ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ |
657 | } ui_u2; | 616 | } ui_u2; |
658 | __fs32 ui_flags; /* 0x64 immutable, append-only... */ | 617 | __fs32 ui_flags; /* 0x64 immutable, append-only... */ |
659 | __fs32 ui_blocks; /* 0x68 blocks in use */ | 618 | __fs32 ui_blocks; /* 0x68 blocks in use */ |
660 | __fs32 ui_gen; /* 0x6c like ext2 i_version, for NFS support */ | 619 | __fs32 ui_gen; /* 0x6c like ext2 i_version, for NFS support */ |
661 | union { | 620 | union { |
662 | struct { | 621 | struct { |
663 | __fs32 ui_shadow; /* 0x70 shadow inode with security data */ | 622 | __fs32 ui_shadow; /* 0x70 shadow inode with security data */ |
664 | __fs32 ui_uid; /* 0x74 long EFT version of uid */ | 623 | __fs32 ui_uid; /* 0x74 long EFT version of uid */ |
665 | __fs32 ui_gid; /* 0x78 long EFT version of gid */ | 624 | __fs32 ui_gid; /* 0x78 long EFT version of gid */ |
666 | __fs32 ui_oeftflag; /* 0x7c reserved */ | 625 | __fs32 ui_oeftflag; /* 0x7c reserved */ |
667 | } ui_sun; | 626 | } ui_sun; |
668 | struct { | 627 | struct { |
669 | __fs32 ui_uid; /* 0x70 File owner */ | 628 | __fs32 ui_uid; /* 0x70 File owner */ |
670 | __fs32 ui_gid; /* 0x74 File group */ | 629 | __fs32 ui_gid; /* 0x74 File group */ |
671 | __fs32 ui_spare[2]; /* 0x78 reserved */ | 630 | __fs32 ui_spare[2]; /* 0x78 reserved */ |
672 | } ui_44; | 631 | } ui_44; |
673 | struct { | 632 | struct { |
674 | __fs32 ui_uid; /* 0x70 */ | 633 | __fs32 ui_uid; /* 0x70 */ |
675 | __fs32 ui_gid; /* 0x74 */ | 634 | __fs32 ui_gid; /* 0x74 */ |
676 | __fs16 ui_modeh; /* 0x78 mode high bits */ | 635 | __fs16 ui_modeh; /* 0x78 mode high bits */ |
677 | __fs16 ui_spare; /* 0x7A unused */ | 636 | __fs16 ui_spare; /* 0x7A unused */ |
678 | __fs32 ui_trans; /* 0x7c filesystem translator */ | 637 | __fs32 ui_trans; /* 0x7c filesystem translator */ |
679 | } ui_hurd; | 638 | } ui_hurd; |
680 | } ui_u3; | 639 | } ui_u3; |
681 | }; | 640 | }; |
682 | 641 | ||
683 | #define UFS_NXADDR 2 /* External addresses in inode. */ | 642 | #define UFS_NXADDR 2 /* External addresses in inode. */ |
684 | struct ufs2_inode { | 643 | struct ufs2_inode { |
685 | __fs16 ui_mode; /* 0: IFMT, permissions; see below. */ | 644 | __fs16 ui_mode; /* 0: IFMT, permissions; see below. */ |
686 | __fs16 ui_nlink; /* 2: File link count. */ | 645 | __fs16 ui_nlink; /* 2: File link count. */ |
687 | __fs32 ui_uid; /* 4: File owner. */ | 646 | __fs32 ui_uid; /* 4: File owner. */ |
688 | __fs32 ui_gid; /* 8: File group. */ | 647 | __fs32 ui_gid; /* 8: File group. */ |
689 | __fs32 ui_blksize; /* 12: Inode blocksize. */ | 648 | __fs32 ui_blksize; /* 12: Inode blocksize. */ |
690 | __fs64 ui_size; /* 16: File byte count. */ | 649 | __fs64 ui_size; /* 16: File byte count. */ |
691 | __fs64 ui_blocks; /* 24: Bytes actually held. */ | 650 | __fs64 ui_blocks; /* 24: Bytes actually held. */ |
692 | __fs64 ui_atime; /* 32: Last access time. */ | 651 | __fs64 ui_atime; /* 32: Last access time. */ |
693 | __fs64 ui_mtime; /* 40: Last modified time. */ | 652 | __fs64 ui_mtime; /* 40: Last modified time. */ |
694 | __fs64 ui_ctime; /* 48: Last inode change time. */ | 653 | __fs64 ui_ctime; /* 48: Last inode change time. */ |
695 | __fs64 ui_birthtime; /* 56: Inode creation time. */ | 654 | __fs64 ui_birthtime; /* 56: Inode creation time. */ |
696 | __fs32 ui_mtimensec; /* 64: Last modified time. */ | 655 | __fs32 ui_mtimensec; /* 64: Last modified time. */ |
697 | __fs32 ui_atimensec; /* 68: Last access time. */ | 656 | __fs32 ui_atimensec; /* 68: Last access time. */ |
698 | __fs32 ui_ctimensec; /* 72: Last inode change time. */ | 657 | __fs32 ui_ctimensec; /* 72: Last inode change time. */ |
699 | __fs32 ui_birthnsec; /* 76: Inode creation time. */ | 658 | __fs32 ui_birthnsec; /* 76: Inode creation time. */ |
700 | __fs32 ui_gen; /* 80: Generation number. */ | 659 | __fs32 ui_gen; /* 80: Generation number. */ |
701 | __fs32 ui_kernflags; /* 84: Kernel flags. */ | 660 | __fs32 ui_kernflags; /* 84: Kernel flags. */ |
702 | __fs32 ui_flags; /* 88: Status flags (chflags). */ | 661 | __fs32 ui_flags; /* 88: Status flags (chflags). */ |
703 | __fs32 ui_extsize; /* 92: External attributes block. */ | 662 | __fs32 ui_extsize; /* 92: External attributes block. */ |
704 | __fs64 ui_extb[UFS_NXADDR];/* 96: External attributes block. */ | 663 | __fs64 ui_extb[UFS_NXADDR];/* 96: External attributes block. */ |
705 | union { | 664 | union { |
706 | struct { | 665 | struct { |
707 | __fs64 ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */ | 666 | __fs64 ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */ |
708 | __fs64 ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/ | 667 | __fs64 ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/ |
709 | } ui_addr; | 668 | } ui_addr; |
710 | __u8 ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ | 669 | __u8 ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ |
711 | } ui_u2; | 670 | } ui_u2; |
712 | __fs64 ui_spare[3]; /* 232: Reserved; currently unused */ | 671 | __fs64 ui_spare[3]; /* 232: Reserved; currently unused */ |
713 | }; | 672 | }; |
714 | 673 | ||
715 | 674 | ||
716 | /* FreeBSD has these in sys/stat.h */ | 675 | /* FreeBSD has these in sys/stat.h */ |
717 | /* ui_flags that can be set by a file owner */ | 676 | /* ui_flags that can be set by a file owner */ |
718 | #define UFS_UF_SETTABLE 0x0000ffff | 677 | #define UFS_UF_SETTABLE 0x0000ffff |
719 | #define UFS_UF_NODUMP 0x00000001 /* do not dump */ | 678 | #define UFS_UF_NODUMP 0x00000001 /* do not dump */ |
720 | #define UFS_UF_IMMUTABLE 0x00000002 /* immutable (can't "change") */ | 679 | #define UFS_UF_IMMUTABLE 0x00000002 /* immutable (can't "change") */ |
721 | #define UFS_UF_APPEND 0x00000004 /* append-only */ | 680 | #define UFS_UF_APPEND 0x00000004 /* append-only */ |
722 | #define UFS_UF_OPAQUE 0x00000008 /* directory is opaque (unionfs) */ | 681 | #define UFS_UF_OPAQUE 0x00000008 /* directory is opaque (unionfs) */ |
723 | #define UFS_UF_NOUNLINK 0x00000010 /* can't be removed or renamed */ | 682 | #define UFS_UF_NOUNLINK 0x00000010 /* can't be removed or renamed */ |
724 | /* ui_flags that only root can set */ | 683 | /* ui_flags that only root can set */ |
725 | #define UFS_SF_SETTABLE 0xffff0000 | 684 | #define UFS_SF_SETTABLE 0xffff0000 |
726 | #define UFS_SF_ARCHIVED 0x00010000 /* archived */ | 685 | #define UFS_SF_ARCHIVED 0x00010000 /* archived */ |
727 | #define UFS_SF_IMMUTABLE 0x00020000 /* immutable (can't "change") */ | 686 | #define UFS_SF_IMMUTABLE 0x00020000 /* immutable (can't "change") */ |
728 | #define UFS_SF_APPEND 0x00040000 /* append-only */ | 687 | #define UFS_SF_APPEND 0x00040000 /* append-only */ |
729 | #define UFS_SF_NOUNLINK 0x00100000 /* can't be removed or renamed */ | 688 | #define UFS_SF_NOUNLINK 0x00100000 /* can't be removed or renamed */ |
730 | 689 | ||
731 | /* | 690 | /* |
732 | * This structure is used for reading disk structures larger | 691 | * This structure is used for reading disk structures larger |
733 | * than the size of fragment. | 692 | * than the size of fragment. |
734 | */ | 693 | */ |
735 | struct ufs_buffer_head { | 694 | struct ufs_buffer_head { |
736 | __u64 fragment; /* first fragment */ | 695 | __u64 fragment; /* first fragment */ |
737 | __u64 count; /* number of fragments */ | 696 | __u64 count; /* number of fragments */ |
738 | struct buffer_head * bh[UFS_MAXFRAG]; /* buffers */ | 697 | struct buffer_head * bh[UFS_MAXFRAG]; /* buffers */ |
739 | }; | 698 | }; |
740 | 699 | ||
741 | struct ufs_cg_private_info { | 700 | struct ufs_cg_private_info { |
742 | struct ufs_buffer_head c_ubh; | 701 | struct ufs_buffer_head c_ubh; |
743 | __u32 c_cgx; /* number of cylidner group */ | 702 | __u32 c_cgx; /* number of cylidner group */ |
744 | __u16 c_ncyl; /* number of cyl's this cg */ | 703 | __u16 c_ncyl; /* number of cyl's this cg */ |
745 | __u16 c_niblk; /* number of inode blocks this cg */ | 704 | __u16 c_niblk; /* number of inode blocks this cg */ |
746 | __u32 c_ndblk; /* number of data blocks this cg */ | 705 | __u32 c_ndblk; /* number of data blocks this cg */ |
747 | __u32 c_rotor; /* position of last used block */ | 706 | __u32 c_rotor; /* position of last used block */ |
748 | __u32 c_frotor; /* position of last used frag */ | 707 | __u32 c_frotor; /* position of last used frag */ |
749 | __u32 c_irotor; /* position of last used inode */ | 708 | __u32 c_irotor; /* position of last used inode */ |
750 | __u32 c_btotoff; /* (__u32) block totals per cylinder */ | 709 | __u32 c_btotoff; /* (__u32) block totals per cylinder */ |
751 | __u32 c_boff; /* (short) free block positions */ | 710 | __u32 c_boff; /* (short) free block positions */ |
752 | __u32 c_iusedoff; /* (char) used inode map */ | 711 | __u32 c_iusedoff; /* (char) used inode map */ |
753 | __u32 c_freeoff; /* (u_char) free block map */ | 712 | __u32 c_freeoff; /* (u_char) free block map */ |
754 | __u32 c_nextfreeoff; /* (u_char) next available space */ | 713 | __u32 c_nextfreeoff; /* (u_char) next available space */ |
755 | __u32 c_clustersumoff;/* (u_int32) counts of avail clusters */ | 714 | __u32 c_clustersumoff;/* (u_int32) counts of avail clusters */ |
756 | __u32 c_clusteroff; /* (u_int8) free cluster map */ | 715 | __u32 c_clusteroff; /* (u_int8) free cluster map */ |
757 | __u32 c_nclusterblks; /* number of clusters this cg */ | 716 | __u32 c_nclusterblks; /* number of clusters this cg */ |
758 | }; | 717 | }; |
759 | 718 | ||
760 | 719 | ||
761 | struct ufs_sb_private_info { | 720 | struct ufs_sb_private_info { |
762 | struct ufs_buffer_head s_ubh; /* buffer containing super block */ | 721 | struct ufs_buffer_head s_ubh; /* buffer containing super block */ |
763 | struct ufs_csum_core cs_total; | 722 | struct ufs_csum_core cs_total; |
764 | __u32 s_sblkno; /* offset of super-blocks in filesys */ | 723 | __u32 s_sblkno; /* offset of super-blocks in filesys */ |
765 | __u32 s_cblkno; /* offset of cg-block in filesys */ | 724 | __u32 s_cblkno; /* offset of cg-block in filesys */ |
766 | __u32 s_iblkno; /* offset of inode-blocks in filesys */ | 725 | __u32 s_iblkno; /* offset of inode-blocks in filesys */ |
767 | __u32 s_dblkno; /* offset of first data after cg */ | 726 | __u32 s_dblkno; /* offset of first data after cg */ |
768 | __u32 s_cgoffset; /* cylinder group offset in cylinder */ | 727 | __u32 s_cgoffset; /* cylinder group offset in cylinder */ |
769 | __u32 s_cgmask; /* used to calc mod fs_ntrak */ | 728 | __u32 s_cgmask; /* used to calc mod fs_ntrak */ |
770 | __u32 s_size; /* number of blocks (fragments) in fs */ | 729 | __u32 s_size; /* number of blocks (fragments) in fs */ |
771 | __u32 s_dsize; /* number of data blocks in fs */ | 730 | __u32 s_dsize; /* number of data blocks in fs */ |
772 | __u64 s_u2_size; /* ufs2: number of blocks (fragments) in fs */ | 731 | __u64 s_u2_size; /* ufs2: number of blocks (fragments) in fs */ |
773 | __u64 s_u2_dsize; /*ufs2: number of data blocks in fs */ | 732 | __u64 s_u2_dsize; /*ufs2: number of data blocks in fs */ |
774 | __u32 s_ncg; /* number of cylinder groups */ | 733 | __u32 s_ncg; /* number of cylinder groups */ |
775 | __u32 s_bsize; /* size of basic blocks */ | 734 | __u32 s_bsize; /* size of basic blocks */ |
776 | __u32 s_fsize; /* size of fragments */ | 735 | __u32 s_fsize; /* size of fragments */ |
777 | __u32 s_fpb; /* fragments per block */ | 736 | __u32 s_fpb; /* fragments per block */ |
778 | __u32 s_minfree; /* minimum percentage of free blocks */ | 737 | __u32 s_minfree; /* minimum percentage of free blocks */ |
779 | __u32 s_bmask; /* `blkoff'' calc of blk offsets */ | 738 | __u32 s_bmask; /* `blkoff'' calc of blk offsets */ |
780 | __u32 s_fmask; /* s_fsize mask */ | 739 | __u32 s_fmask; /* s_fsize mask */ |
781 | __u32 s_bshift; /* `lblkno'' calc of logical blkno */ | 740 | __u32 s_bshift; /* `lblkno'' calc of logical blkno */ |
782 | __u32 s_fshift; /* s_fsize shift */ | 741 | __u32 s_fshift; /* s_fsize shift */ |
783 | __u32 s_fpbshift; /* fragments per block shift */ | 742 | __u32 s_fpbshift; /* fragments per block shift */ |
784 | __u32 s_fsbtodb; /* fsbtodb and dbtofsb shift constant */ | 743 | __u32 s_fsbtodb; /* fsbtodb and dbtofsb shift constant */ |
785 | __u32 s_sbsize; /* actual size of super block */ | 744 | __u32 s_sbsize; /* actual size of super block */ |
786 | __u32 s_csmask; /* csum block offset */ | 745 | __u32 s_csmask; /* csum block offset */ |
787 | __u32 s_csshift; /* csum block number */ | 746 | __u32 s_csshift; /* csum block number */ |
788 | __u32 s_nindir; /* value of NINDIR */ | 747 | __u32 s_nindir; /* value of NINDIR */ |
789 | __u32 s_inopb; /* value of INOPB */ | 748 | __u32 s_inopb; /* value of INOPB */ |
790 | __u32 s_nspf; /* value of NSPF */ | 749 | __u32 s_nspf; /* value of NSPF */ |
791 | __u32 s_npsect; /* # sectors/track including spares */ | 750 | __u32 s_npsect; /* # sectors/track including spares */ |
792 | __u32 s_interleave; /* hardware sector interleave */ | 751 | __u32 s_interleave; /* hardware sector interleave */ |
793 | __u32 s_trackskew; /* sector 0 skew, per track */ | 752 | __u32 s_trackskew; /* sector 0 skew, per track */ |
794 | __u64 s_csaddr; /* blk addr of cyl grp summary area */ | 753 | __u64 s_csaddr; /* blk addr of cyl grp summary area */ |
795 | __u32 s_cssize; /* size of cyl grp summary area */ | 754 | __u32 s_cssize; /* size of cyl grp summary area */ |
796 | __u32 s_cgsize; /* cylinder group size */ | 755 | __u32 s_cgsize; /* cylinder group size */ |
797 | __u32 s_ntrak; /* tracks per cylinder */ | 756 | __u32 s_ntrak; /* tracks per cylinder */ |
798 | __u32 s_nsect; /* sectors per track */ | 757 | __u32 s_nsect; /* sectors per track */ |
799 | __u32 s_spc; /* sectors per cylinder */ | 758 | __u32 s_spc; /* sectors per cylinder */ |
800 | __u32 s_ipg; /* inodes per cylinder group */ | 759 | __u32 s_ipg; /* inodes per cylinder group */ |
801 | __u32 s_fpg; /* fragments per group */ | 760 | __u32 s_fpg; /* fragments per group */ |
802 | __u32 s_cpc; /* cyl per cycle in postbl */ | 761 | __u32 s_cpc; /* cyl per cycle in postbl */ |
803 | __s32 s_contigsumsize;/* size of cluster summary array, 44bsd */ | 762 | __s32 s_contigsumsize;/* size of cluster summary array, 44bsd */ |
804 | __s64 s_qbmask; /* ~usb_bmask */ | 763 | __s64 s_qbmask; /* ~usb_bmask */ |
805 | __s64 s_qfmask; /* ~usb_fmask */ | 764 | __s64 s_qfmask; /* ~usb_fmask */ |
806 | __s32 s_postblformat; /* format of positional layout tables */ | 765 | __s32 s_postblformat; /* format of positional layout tables */ |
807 | __s32 s_nrpos; /* number of rotational positions */ | 766 | __s32 s_nrpos; /* number of rotational positions */ |
808 | __s32 s_postbloff; /* (__s16) rotation block list head */ | 767 | __s32 s_postbloff; /* (__s16) rotation block list head */ |
809 | __s32 s_rotbloff; /* (__u8) blocks for each rotation */ | 768 | __s32 s_rotbloff; /* (__u8) blocks for each rotation */ |
810 | 769 | ||
811 | __u32 s_fpbmask; /* fragments per block mask */ | 770 | __u32 s_fpbmask; /* fragments per block mask */ |
812 | __u32 s_apb; /* address per block */ | 771 | __u32 s_apb; /* address per block */ |
813 | __u32 s_2apb; /* address per block^2 */ | 772 | __u32 s_2apb; /* address per block^2 */ |
814 | __u32 s_3apb; /* address per block^3 */ | 773 | __u32 s_3apb; /* address per block^3 */ |
815 | __u32 s_apbmask; /* address per block mask */ | 774 | __u32 s_apbmask; /* address per block mask */ |
816 | __u32 s_apbshift; /* address per block shift */ | 775 | __u32 s_apbshift; /* address per block shift */ |
817 | __u32 s_2apbshift; /* address per block shift * 2 */ | 776 | __u32 s_2apbshift; /* address per block shift * 2 */ |
818 | __u32 s_3apbshift; /* address per block shift * 3 */ | 777 | __u32 s_3apbshift; /* address per block shift * 3 */ |
819 | __u32 s_nspfshift; /* number of sector per fragment shift */ | 778 | __u32 s_nspfshift; /* number of sector per fragment shift */ |
820 | __u32 s_nspb; /* number of sector per block */ | 779 | __u32 s_nspb; /* number of sector per block */ |
821 | __u32 s_inopf; /* inodes per fragment */ | 780 | __u32 s_inopf; /* inodes per fragment */ |
822 | __u32 s_sbbase; /* offset of NeXTstep superblock */ | 781 | __u32 s_sbbase; /* offset of NeXTstep superblock */ |
823 | __u32 s_bpf; /* bits per fragment */ | 782 | __u32 s_bpf; /* bits per fragment */ |
824 | __u32 s_bpfshift; /* bits per fragment shift*/ | 783 | __u32 s_bpfshift; /* bits per fragment shift*/ |
825 | __u32 s_bpfmask; /* bits per fragment mask */ | 784 | __u32 s_bpfmask; /* bits per fragment mask */ |
826 | 785 | ||
827 | __u32 s_maxsymlinklen;/* upper limit on fast symlinks' size */ | 786 | __u32 s_maxsymlinklen;/* upper limit on fast symlinks' size */ |
828 | __s32 fs_magic; /* filesystem magic */ | 787 | __s32 fs_magic; /* filesystem magic */ |
829 | unsigned int s_dirblksize; | 788 | unsigned int s_dirblksize; |
830 | }; | 789 | }; |
831 | 790 | ||
832 | /* | 791 | /* |
833 | * Sizes of this structures are: | 792 | * Sizes of this structures are: |
834 | * ufs_super_block_first 512 | 793 | * ufs_super_block_first 512 |
835 | * ufs_super_block_second 512 | 794 | * ufs_super_block_second 512 |
836 | * ufs_super_block_third 356 | 795 | * ufs_super_block_third 356 |
837 | */ | 796 | */ |
838 | struct ufs_super_block_first { | 797 | struct ufs_super_block_first { |
839 | union { | 798 | union { |
840 | struct { | 799 | struct { |
841 | __fs32 fs_link; /* UNUSED */ | 800 | __fs32 fs_link; /* UNUSED */ |
842 | } fs_42; | 801 | } fs_42; |
843 | struct { | 802 | struct { |
844 | __fs32 fs_state; /* file system state flag */ | 803 | __fs32 fs_state; /* file system state flag */ |
845 | } fs_sun; | 804 | } fs_sun; |
846 | } fs_u0; | 805 | } fs_u0; |
847 | __fs32 fs_rlink; | 806 | __fs32 fs_rlink; |
848 | __fs32 fs_sblkno; | 807 | __fs32 fs_sblkno; |
849 | __fs32 fs_cblkno; | 808 | __fs32 fs_cblkno; |
850 | __fs32 fs_iblkno; | 809 | __fs32 fs_iblkno; |
851 | __fs32 fs_dblkno; | 810 | __fs32 fs_dblkno; |
852 | __fs32 fs_cgoffset; | 811 | __fs32 fs_cgoffset; |
853 | __fs32 fs_cgmask; | 812 | __fs32 fs_cgmask; |
854 | __fs32 fs_time; | 813 | __fs32 fs_time; |
855 | __fs32 fs_size; | 814 | __fs32 fs_size; |
856 | __fs32 fs_dsize; | 815 | __fs32 fs_dsize; |
857 | __fs32 fs_ncg; | 816 | __fs32 fs_ncg; |
858 | __fs32 fs_bsize; | 817 | __fs32 fs_bsize; |
859 | __fs32 fs_fsize; | 818 | __fs32 fs_fsize; |
860 | __fs32 fs_frag; | 819 | __fs32 fs_frag; |
861 | __fs32 fs_minfree; | 820 | __fs32 fs_minfree; |
862 | __fs32 fs_rotdelay; | 821 | __fs32 fs_rotdelay; |
863 | __fs32 fs_rps; | 822 | __fs32 fs_rps; |
864 | __fs32 fs_bmask; | 823 | __fs32 fs_bmask; |
865 | __fs32 fs_fmask; | 824 | __fs32 fs_fmask; |
866 | __fs32 fs_bshift; | 825 | __fs32 fs_bshift; |
867 | __fs32 fs_fshift; | 826 | __fs32 fs_fshift; |
868 | __fs32 fs_maxcontig; | 827 | __fs32 fs_maxcontig; |
869 | __fs32 fs_maxbpg; | 828 | __fs32 fs_maxbpg; |
870 | __fs32 fs_fragshift; | 829 | __fs32 fs_fragshift; |
871 | __fs32 fs_fsbtodb; | 830 | __fs32 fs_fsbtodb; |
872 | __fs32 fs_sbsize; | 831 | __fs32 fs_sbsize; |
873 | __fs32 fs_csmask; | 832 | __fs32 fs_csmask; |
874 | __fs32 fs_csshift; | 833 | __fs32 fs_csshift; |
875 | __fs32 fs_nindir; | 834 | __fs32 fs_nindir; |
876 | __fs32 fs_inopb; | 835 | __fs32 fs_inopb; |
877 | __fs32 fs_nspf; | 836 | __fs32 fs_nspf; |
878 | __fs32 fs_optim; | 837 | __fs32 fs_optim; |
879 | union { | 838 | union { |
880 | struct { | 839 | struct { |
881 | __fs32 fs_npsect; | 840 | __fs32 fs_npsect; |
882 | } fs_sun; | 841 | } fs_sun; |
883 | struct { | 842 | struct { |
884 | __fs32 fs_state; | 843 | __fs32 fs_state; |
885 | } fs_sunx86; | 844 | } fs_sunx86; |
886 | } fs_u1; | 845 | } fs_u1; |
887 | __fs32 fs_interleave; | 846 | __fs32 fs_interleave; |
888 | __fs32 fs_trackskew; | 847 | __fs32 fs_trackskew; |
889 | __fs32 fs_id[2]; | 848 | __fs32 fs_id[2]; |
890 | __fs32 fs_csaddr; | 849 | __fs32 fs_csaddr; |
891 | __fs32 fs_cssize; | 850 | __fs32 fs_cssize; |
892 | __fs32 fs_cgsize; | 851 | __fs32 fs_cgsize; |
893 | __fs32 fs_ntrak; | 852 | __fs32 fs_ntrak; |
894 | __fs32 fs_nsect; | 853 | __fs32 fs_nsect; |
895 | __fs32 fs_spc; | 854 | __fs32 fs_spc; |
896 | __fs32 fs_ncyl; | 855 | __fs32 fs_ncyl; |
897 | __fs32 fs_cpg; | 856 | __fs32 fs_cpg; |
898 | __fs32 fs_ipg; | 857 | __fs32 fs_ipg; |
899 | __fs32 fs_fpg; | 858 | __fs32 fs_fpg; |
900 | struct ufs_csum fs_cstotal; | 859 | struct ufs_csum fs_cstotal; |
901 | __s8 fs_fmod; | 860 | __s8 fs_fmod; |
902 | __s8 fs_clean; | 861 | __s8 fs_clean; |
903 | __s8 fs_ronly; | 862 | __s8 fs_ronly; |
904 | __s8 fs_flags; | 863 | __s8 fs_flags; |
905 | __s8 fs_fsmnt[UFS_MAXMNTLEN - 212]; | 864 | __s8 fs_fsmnt[UFS_MAXMNTLEN - 212]; |
906 | 865 | ||
907 | }; | 866 | }; |
908 | 867 | ||
909 | struct ufs_super_block_second { | 868 | struct ufs_super_block_second { |
910 | union { | 869 | union { |
911 | struct { | 870 | struct { |
912 | __s8 fs_fsmnt[212]; | 871 | __s8 fs_fsmnt[212]; |
913 | __fs32 fs_cgrotor; | 872 | __fs32 fs_cgrotor; |
914 | __fs32 fs_csp[UFS_MAXCSBUFS]; | 873 | __fs32 fs_csp[UFS_MAXCSBUFS]; |
915 | __fs32 fs_maxcluster; | 874 | __fs32 fs_maxcluster; |
916 | __fs32 fs_cpc; | 875 | __fs32 fs_cpc; |
917 | __fs16 fs_opostbl[82]; | 876 | __fs16 fs_opostbl[82]; |
918 | } fs_u1; | 877 | } fs_u1; |
919 | struct { | 878 | struct { |
920 | __s8 fs_fsmnt[UFS2_MAXMNTLEN - UFS_MAXMNTLEN + 212]; | 879 | __s8 fs_fsmnt[UFS2_MAXMNTLEN - UFS_MAXMNTLEN + 212]; |
921 | __u8 fs_volname[UFS2_MAXVOLLEN]; | 880 | __u8 fs_volname[UFS2_MAXVOLLEN]; |
922 | __fs64 fs_swuid; | 881 | __fs64 fs_swuid; |
923 | __fs32 fs_pad; | 882 | __fs32 fs_pad; |
924 | __fs32 fs_cgrotor; | 883 | __fs32 fs_cgrotor; |
925 | __fs32 fs_ocsp[UFS2_NOCSPTRS]; | 884 | __fs32 fs_ocsp[UFS2_NOCSPTRS]; |
926 | __fs32 fs_contigdirs; | 885 | __fs32 fs_contigdirs; |
927 | __fs32 fs_csp; | 886 | __fs32 fs_csp; |
928 | __fs32 fs_maxcluster; | 887 | __fs32 fs_maxcluster; |
929 | __fs32 fs_active; | 888 | __fs32 fs_active; |
930 | __fs32 fs_old_cpc; | 889 | __fs32 fs_old_cpc; |
931 | __fs32 fs_maxbsize; | 890 | __fs32 fs_maxbsize; |
932 | __fs64 fs_sparecon64[17]; | 891 | __fs64 fs_sparecon64[17]; |
933 | __fs64 fs_sblockloc; | 892 | __fs64 fs_sblockloc; |
934 | __fs64 cs_ndir; | 893 | __fs64 cs_ndir; |
935 | __fs64 cs_nbfree; | 894 | __fs64 cs_nbfree; |
936 | } fs_u2; | 895 | } fs_u2; |
937 | } fs_un; | 896 | } fs_un; |
938 | }; | 897 | }; |
939 | 898 | ||
940 | struct ufs_super_block_third { | 899 | struct ufs_super_block_third { |
941 | union { | 900 | union { |
942 | struct { | 901 | struct { |
943 | __fs16 fs_opostbl[46]; | 902 | __fs16 fs_opostbl[46]; |
944 | } fs_u1; | 903 | } fs_u1; |
945 | struct { | 904 | struct { |
946 | __fs64 cs_nifree; /* number of free inodes */ | 905 | __fs64 cs_nifree; /* number of free inodes */ |
947 | __fs64 cs_nffree; /* number of free frags */ | 906 | __fs64 cs_nffree; /* number of free frags */ |
948 | __fs64 cs_numclusters; /* number of free clusters */ | 907 | __fs64 cs_numclusters; /* number of free clusters */ |
949 | __fs64 cs_spare[3]; /* future expansion */ | 908 | __fs64 cs_spare[3]; /* future expansion */ |
950 | struct ufs_timeval fs_time; /* last time written */ | 909 | struct ufs_timeval fs_time; /* last time written */ |
951 | __fs64 fs_size; /* number of blocks in fs */ | 910 | __fs64 fs_size; /* number of blocks in fs */ |
952 | __fs64 fs_dsize; /* number of data blocks in fs */ | 911 | __fs64 fs_dsize; /* number of data blocks in fs */ |
953 | __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ | 912 | __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ |
954 | __fs64 fs_pendingblocks;/* blocks in process of being freed */ | 913 | __fs64 fs_pendingblocks;/* blocks in process of being freed */ |
955 | __fs32 fs_pendinginodes;/*inodes in process of being freed */ | 914 | __fs32 fs_pendinginodes;/*inodes in process of being freed */ |
956 | } __attribute__ ((packed)) fs_u2; | 915 | } __attribute__ ((packed)) fs_u2; |
957 | } fs_un1; | 916 | } fs_un1; |
958 | union { | 917 | union { |
959 | struct { | 918 | struct { |
960 | __fs32 fs_sparecon[53];/* reserved for future constants */ | 919 | __fs32 fs_sparecon[53];/* reserved for future constants */ |
961 | __fs32 fs_reclaim; | 920 | __fs32 fs_reclaim; |
962 | __fs32 fs_sparecon2[1]; | 921 | __fs32 fs_sparecon2[1]; |
963 | __fs32 fs_state; /* file system state time stamp */ | 922 | __fs32 fs_state; /* file system state time stamp */ |
964 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 923 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
965 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 924 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
966 | } fs_sun; | 925 | } fs_sun; |
967 | struct { | 926 | struct { |
968 | __fs32 fs_sparecon[53];/* reserved for future constants */ | 927 | __fs32 fs_sparecon[53];/* reserved for future constants */ |
969 | __fs32 fs_reclaim; | 928 | __fs32 fs_reclaim; |
970 | __fs32 fs_sparecon2[1]; | 929 | __fs32 fs_sparecon2[1]; |
971 | __fs32 fs_npsect; /* # sectors/track including spares */ | 930 | __fs32 fs_npsect; /* # sectors/track including spares */ |
972 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 931 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
973 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 932 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
974 | } fs_sunx86; | 933 | } fs_sunx86; |
975 | struct { | 934 | struct { |
976 | __fs32 fs_sparecon[50];/* reserved for future constants */ | 935 | __fs32 fs_sparecon[50];/* reserved for future constants */ |
977 | __fs32 fs_contigsumsize;/* size of cluster summary array */ | 936 | __fs32 fs_contigsumsize;/* size of cluster summary array */ |
978 | __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ | 937 | __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ |
979 | __fs32 fs_inodefmt; /* format of on-disk inodes */ | 938 | __fs32 fs_inodefmt; /* format of on-disk inodes */ |
980 | __fs32 fs_maxfilesize[2]; /* max representable file size */ | 939 | __fs32 fs_maxfilesize[2]; /* max representable file size */ |
981 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ | 940 | __fs32 fs_qbmask[2]; /* ~usb_bmask */ |
982 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ | 941 | __fs32 fs_qfmask[2]; /* ~usb_fmask */ |
983 | __fs32 fs_state; /* file system state time stamp */ | 942 | __fs32 fs_state; /* file system state time stamp */ |
984 | } fs_44; | 943 | } fs_44; |
985 | } fs_un2; | 944 | } fs_un2; |
986 | __fs32 fs_postblformat; | 945 | __fs32 fs_postblformat; |
987 | __fs32 fs_nrpos; | 946 | __fs32 fs_nrpos; |
988 | __fs32 fs_postbloff; | 947 | __fs32 fs_postbloff; |
989 | __fs32 fs_rotbloff; | 948 | __fs32 fs_rotbloff; |
990 | __fs32 fs_magic; | 949 | __fs32 fs_magic; |
991 | __u8 fs_space[1]; | 950 | __u8 fs_space[1]; |
992 | }; | 951 | }; |
993 | |||
994 | #ifdef __KERNEL__ | ||
995 | |||
996 | /* balloc.c */ | ||
997 | extern void ufs_free_fragments (struct inode *, u64, unsigned); | ||
998 | extern void ufs_free_blocks (struct inode *, u64, unsigned); | ||
999 | extern u64 ufs_new_fragments(struct inode *, void *, u64, u64, | ||
1000 | unsigned, int *, struct page *); | ||
1001 | |||
1002 | /* cylinder.c */ | ||
1003 | extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned); | ||
1004 | extern void ufs_put_cylinder (struct super_block *, unsigned); | ||
1005 | |||
1006 | /* dir.c */ | ||
1007 | extern const struct inode_operations ufs_dir_inode_operations; | ||
1008 | extern int ufs_add_link (struct dentry *, struct inode *); | ||
1009 | extern ino_t ufs_inode_by_name(struct inode *, struct dentry *); | ||
1010 | extern int ufs_make_empty(struct inode *, struct inode *); | ||
1011 | extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **); | ||
1012 | extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *); | ||
1013 | extern int ufs_empty_dir (struct inode *); | ||
1014 | extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **); | ||
1015 | extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, | ||
1016 | struct page *page, struct inode *inode); | ||
1017 | |||
1018 | /* file.c */ | ||
1019 | extern const struct inode_operations ufs_file_inode_operations; | ||
1020 | extern const struct file_operations ufs_file_operations; | ||
1021 | |||
1022 | extern const struct address_space_operations ufs_aops; | ||
1023 | |||
1024 | /* ialloc.c */ | ||
1025 | extern void ufs_free_inode (struct inode *inode); | ||
1026 | extern struct inode * ufs_new_inode (struct inode *, int); | ||
1027 | |||
1028 | /* inode.c */ | ||
1029 | extern void ufs_read_inode (struct inode *); | ||
1030 | extern void ufs_put_inode (struct inode *); | ||
1031 | extern int ufs_write_inode (struct inode *, int); | ||
1032 | extern int ufs_sync_inode (struct inode *); | ||
1033 | extern void ufs_delete_inode (struct inode *); | ||
1034 | extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); | ||
1035 | extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); | ||
1036 | |||
1037 | /* namei.c */ | ||
1038 | extern const struct file_operations ufs_dir_operations; | ||
1039 | |||
1040 | /* super.c */ | ||
1041 | extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
1042 | extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
1043 | extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | ||
1044 | |||
1045 | /* symlink.c */ | ||
1046 | extern const struct inode_operations ufs_fast_symlink_inode_operations; | ||
1047 | |||
1048 | /* truncate.c */ | ||
1049 | extern int ufs_truncate (struct inode *, loff_t); | ||
1050 | |||
1051 | static inline struct ufs_sb_info *UFS_SB(struct super_block *sb) | ||
1052 | { | ||
1053 | return sb->s_fs_info; | ||
1054 | } | ||
1055 | |||
1056 | static inline struct ufs_inode_info *UFS_I(struct inode *inode) | ||
1057 | { | ||
1058 | return container_of(inode, struct ufs_inode_info, vfs_inode); | ||
1059 | } | ||
1060 | |||
1061 | /* | ||
1062 | * Give cylinder group number for a file system block. | ||
1063 | * Give cylinder group block number for a file system block. | ||
1064 | */ | ||
1065 | /* #define ufs_dtog(d) ((d) / uspi->s_fpg) */ | ||
1066 | static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b) | ||
1067 | { | ||
1068 | do_div(b, uspi->s_fpg); | ||
1069 | return b; | ||
1070 | } | ||
1071 | /* #define ufs_dtogd(d) ((d) % uspi->s_fpg) */ | ||
1072 | static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b) | ||
1073 | { | ||
1074 | return do_div(b, uspi->s_fpg); | ||
1075 | } | ||
1076 | |||
1077 | #endif /* __KERNEL__ */ | ||
1078 | 952 | ||
1079 | #endif /* __LINUX_UFS_FS_H */ | 953 | #endif /* __LINUX_UFS_FS_H */ |
1080 | 954 |
include/linux/ufs_fs_i.h
1 | /* | File was deleted | |
2 | * linux/include/linux/ufs_fs_i.h | ||
3 | * | ||
4 | * Copyright (C) 1996 | ||
5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) | ||
6 | * Laboratory for Computer Science Research Computing Facility | ||
7 | * Rutgers, The State University of New Jersey | ||
8 | * | ||
9 | * NeXTstep support added on February 5th 1998 by | ||
10 | * Niels Kristian Bech Jensen <nkbj@image.dk>. | ||
11 | */ | ||
12 | |||
13 | #ifndef _LINUX_UFS_FS_I_H | ||
14 | #define _LINUX_UFS_FS_I_H | ||
15 | |||
16 | struct ufs_inode_info { | ||
17 | union { | ||
18 | __fs32 i_data[15]; | ||
19 | __u8 i_symlink[4*15]; | ||
20 | __fs64 u2_i_data[15]; | ||
21 | } i_u1; | ||
22 | __u32 i_flags; | ||
23 | __u32 i_shadow; | ||
24 | __u32 i_unused1; | ||
25 | __u32 i_unused2; | ||
26 | __u32 i_oeftflag; | ||
27 | __u16 i_osync; | ||
28 | __u64 i_lastfrag; | ||
29 | __u32 i_dir_start_lookup; | ||
30 | struct inode vfs_inode; | ||
31 | }; | ||
32 | |||
33 | #endif /* _LINUX_UFS_FS_I_H */ | ||
34 | 1 | /* |
include/linux/ufs_fs_sb.h
1 | /* | File was deleted | |
2 | * linux/include/linux/ufs_fs_sb.h | ||
3 | * | ||
4 | * Copyright (C) 1996 | ||
5 | * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) | ||
6 | * Laboratory for Computer Science Research Computing Facility | ||
7 | * Rutgers, The State University of New Jersey | ||
8 | * | ||
9 | * $Id: ufs_fs_sb.h,v 1.8 1998/05/06 12:04:40 jj Exp $ | ||
10 | * | ||
11 | * Write support by Daniel Pirkl <daniel.pirkl@email.cz> | ||
12 | */ | ||
13 | |||
14 | #ifndef __LINUX_UFS_FS_SB_H | ||
15 | #define __LINUX_UFS_FS_SB_H | ||
16 | |||
17 | |||
18 | #define UFS_MAX_GROUP_LOADED 8 | ||
19 | #define UFS_CGNO_EMPTY ((unsigned)-1) | ||
20 | |||
21 | struct ufs_sb_private_info; | ||
22 | struct ufs_cg_private_info; | ||
23 | struct ufs_csum; | ||
24 | |||
25 | struct ufs_sb_info { | ||
26 | struct ufs_sb_private_info * s_uspi; | ||
27 | struct ufs_csum * s_csp; | ||
28 | unsigned s_bytesex; | ||
29 | unsigned s_flags; | ||
30 | struct buffer_head ** s_ucg; | ||
31 | struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED]; | ||
32 | unsigned s_cgno[UFS_MAX_GROUP_LOADED]; | ||
33 | unsigned short s_cg_loaded; | ||
34 | unsigned s_mount_opt; | ||
35 | }; | ||
36 | |||
37 | #endif | ||
38 | 1 | /* |