Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] bfs: fix endianness, signedness; add trivial bugfix

* Makes BFS code endianness-clean.

* Fixes some signedness warnings.

* Fixes a problem in fs/bfs/inode.c:164 where inodes not synced to disk
don't get fully marked as clean. Here's how to reproduce it:

# mount -o loop -t bfs /bfs.img /mnt
# df -i /mnt
Filesystem Inodes IUsed IFree IUse% Mounted on
/bfs.img 48 1 47 3% /mnt
# df -k /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/bfs.img 512 5 508 1% /mnt
# cp 60k-archive.zip /mnt/mt.zip
# df -k /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/bfs.img 512 65 447 13% /mnt
# df -i /mnt
Filesystem Inodes IUsed IFree IUse% Mounted on
/bfs.img 48 2 46 5% /mnt
# rm /mnt/mt.zip
# echo $?
0

[If the unlink happens before the buffers flush, the following happens:]

# df -i /mnt
Filesystem Inodes IUsed IFree IUse% Mounted on
/bfs.img 48 2 46 5% /mnt
# df -k /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/bfs.img 512 65 447 13% /mnt

fs/bfs/bfs.h | 1

Signed-off-by: Andrew Stribblehill <ads@wompom.org>
Cc: <tigran@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Andrew Stribblehill and committed by
Linus Torvalds
fac92bec 383f2835

+92 -80
-1
fs/bfs/bfs.h
··· 20 20 unsigned long si_lasti; 21 21 unsigned long * si_imap; 22 22 struct buffer_head * si_sbh; /* buffer header w/superblock */ 23 - struct bfs_super_block * si_bfs_sb; /* superblock in si_sbh->b_data */ 24 23 }; 25 24 26 25 /*
+13 -12
fs/bfs/dir.c
··· 2 2 * fs/bfs/dir.c 3 3 * BFS directory operations. 4 4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> 5 + * Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005 5 6 */ 6 7 7 8 #include <linux/time.h> ··· 21 20 #define dprintf(x...) 22 21 #endif 23 22 24 - static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino); 23 + static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino); 25 24 static struct buffer_head * bfs_find_entry(struct inode * dir, 26 - const char * name, int namelen, struct bfs_dirent ** res_dir); 25 + const unsigned char * name, int namelen, struct bfs_dirent ** res_dir); 27 26 28 27 static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) 29 28 { ··· 54 53 de = (struct bfs_dirent *)(bh->b_data + offset); 55 54 if (de->ino) { 56 55 int size = strnlen(de->name, BFS_NAMELEN); 57 - if (filldir(dirent, de->name, size, f->f_pos, de->ino, DT_UNKNOWN) < 0) { 56 + if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) { 58 57 brelse(bh); 59 58 unlock_kernel(); 60 59 return 0; ··· 108 107 inode->i_mapping->a_ops = &bfs_aops; 109 108 inode->i_mode = mode; 110 109 inode->i_ino = ino; 111 - BFS_I(inode)->i_dsk_ino = ino; 110 + BFS_I(inode)->i_dsk_ino = cpu_to_le16(ino); 112 111 BFS_I(inode)->i_sblock = 0; 113 112 BFS_I(inode)->i_eblock = 0; 114 113 insert_inode_hash(inode); ··· 140 139 lock_kernel(); 141 140 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); 142 141 if (bh) { 143 - unsigned long ino = le32_to_cpu(de->ino); 142 + unsigned long ino = (unsigned long)le16_to_cpu(de->ino); 144 143 brelse(bh); 145 144 inode = iget(dir->i_sb, ino); 146 145 if (!inode) { ··· 184 183 inode = dentry->d_inode; 185 184 lock_kernel(); 186 185 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); 187 - if (!bh || de->ino != inode->i_ino) 186 + if (!bh || le16_to_cpu(de->ino) != inode->i_ino) 188 187 goto out_brelse; 189 188 190 189 if (!inode->i_nlink) { ··· 225 224 old_dentry->d_name.name, 226 225 old_dentry->d_name.len, &old_de); 227 226 228 - if (!old_bh || old_de->ino != old_inode->i_ino) 227 + if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino) 229 228 goto end_rename; 230 229 231 230 error = -EPERM; ··· 271 270 .rename = bfs_rename, 272 271 }; 273 272 274 - static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino) 273 + static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino) 275 274 { 276 275 struct buffer_head * bh; 277 276 struct bfs_dirent * de; ··· 305 304 } 306 305 dir->i_mtime = CURRENT_TIME_SEC; 307 306 mark_inode_dirty(dir); 308 - de->ino = ino; 307 + de->ino = cpu_to_le16((u16)ino); 309 308 for (i=0; i<BFS_NAMELEN; i++) 310 309 de->name[i] = (i < namelen) ? name[i] : 0; 311 310 mark_buffer_dirty(bh); ··· 318 317 return -ENOSPC; 319 318 } 320 319 321 - static inline int bfs_namecmp(int len, const char * name, const char * buffer) 320 + static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer) 322 321 { 323 322 if (len < BFS_NAMELEN && buffer[len]) 324 323 return 0; ··· 326 325 } 327 326 328 327 static struct buffer_head * bfs_find_entry(struct inode * dir, 329 - const char * name, int namelen, struct bfs_dirent ** res_dir) 328 + const unsigned char * name, int namelen, struct bfs_dirent ** res_dir) 330 329 { 331 330 unsigned long block, offset; 332 331 struct buffer_head * bh; ··· 347 346 } 348 347 de = (struct bfs_dirent *)(bh->b_data + offset); 349 348 offset += BFS_DIRENT_SIZE; 350 - if (de->ino && bfs_namecmp(namelen, name, de->name)) { 349 + if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) { 351 350 *res_dir = de; 352 351 return bh; 353 352 }
+13 -10
fs/bfs/file.c
··· 40 40 return 0; 41 41 } 42 42 43 - static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned long end, 44 - unsigned long where) 43 + static int bfs_move_blocks(struct super_block *sb, unsigned long start, 44 + unsigned long end, unsigned long where) 45 45 { 46 46 unsigned long i; 47 47 ··· 57 57 static int bfs_get_block(struct inode * inode, sector_t block, 58 58 struct buffer_head * bh_result, int create) 59 59 { 60 - long phys; 60 + unsigned long phys; 61 61 int err; 62 62 struct super_block *sb = inode->i_sb; 63 63 struct bfs_sb_info *info = BFS_SB(sb); 64 64 struct bfs_inode_info *bi = BFS_I(inode); 65 65 struct buffer_head *sbh = info->si_sbh; 66 66 67 - if (block < 0 || block > info->si_blocks) 67 + if (block > info->si_blocks) 68 68 return -EIO; 69 69 70 70 phys = bi->i_sblock + block; 71 71 if (!create) { 72 72 if (phys <= bi->i_eblock) { 73 - dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys); 73 + dprintf("c=%d, b=%08lx, phys=%09lx (granted)\n", 74 + create, (unsigned long)block, phys); 74 75 map_bh(bh_result, sb, phys); 75 76 } 76 77 return 0; ··· 81 80 of blocks allocated for this file, we can grant it */ 82 81 if (inode->i_size && phys <= bi->i_eblock) { 83 82 dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 84 - create, block, phys); 83 + create, (unsigned long)block, phys); 85 84 map_bh(bh_result, sb, phys); 86 85 return 0; 87 86 } ··· 89 88 /* the rest has to be protected against itself */ 90 89 lock_kernel(); 91 90 92 - /* if the last data block for this file is the last allocated block, we can 93 - extend the file trivially, without moving it anywhere */ 91 + /* if the last data block for this file is the last allocated 92 + block, we can extend the file trivially, without moving it 93 + anywhere */ 94 94 if (bi->i_eblock == info->si_lf_eblk) { 95 95 dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 96 - create, block, phys); 96 + create, (unsigned long)block, phys); 97 97 map_bh(bh_result, sb, phys); 98 98 info->si_freeb -= phys - bi->i_eblock; 99 99 info->si_lf_eblk = bi->i_eblock = phys; ··· 116 114 } else 117 115 err = 0; 118 116 119 - dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys); 117 + dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", 118 + create, (unsigned long)block, phys); 120 119 bi->i_sblock = phys; 121 120 phys += block; 122 121 info->si_lf_eblk = bi->i_eblock = phys;
+54 -46
fs/bfs/inode.c
··· 3 3 * BFS superblock and inode operations. 4 4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> 5 5 * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds. 6 + * 7 + * Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005. 6 8 */ 7 9 8 10 #include <linux/module.h> ··· 56 54 off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; 57 55 di = (struct bfs_inode *)bh->b_data + off; 58 56 59 - inode->i_mode = 0x0000FFFF & di->i_mode; 60 - if (di->i_vtype == BFS_VDIR) { 57 + inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); 58 + if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { 61 59 inode->i_mode |= S_IFDIR; 62 60 inode->i_op = &bfs_dir_inops; 63 61 inode->i_fop = &bfs_dir_operations; 64 - } else if (di->i_vtype == BFS_VREG) { 62 + } else if (le32_to_cpu(di->i_vtype) == BFS_VREG) { 65 63 inode->i_mode |= S_IFREG; 66 64 inode->i_op = &bfs_file_inops; 67 65 inode->i_fop = &bfs_file_operations; 68 66 inode->i_mapping->a_ops = &bfs_aops; 69 67 } 70 68 71 - inode->i_uid = di->i_uid; 72 - inode->i_gid = di->i_gid; 73 - inode->i_nlink = di->i_nlink; 69 + BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); 70 + BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); 71 + inode->i_uid = le32_to_cpu(di->i_uid); 72 + inode->i_gid = le32_to_cpu(di->i_gid); 73 + inode->i_nlink = le32_to_cpu(di->i_nlink); 74 74 inode->i_size = BFS_FILESIZE(di); 75 75 inode->i_blocks = BFS_FILEBLOCKS(di); 76 + if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks); 76 77 inode->i_blksize = PAGE_SIZE; 77 - inode->i_atime.tv_sec = di->i_atime; 78 - inode->i_mtime.tv_sec = di->i_mtime; 79 - inode->i_ctime.tv_sec = di->i_ctime; 78 + inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); 79 + inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); 80 + inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); 80 81 inode->i_atime.tv_nsec = 0; 81 82 inode->i_mtime.tv_nsec = 0; 82 83 inode->i_ctime.tv_nsec = 0; 83 - BFS_I(inode)->i_dsk_ino = di->i_ino; /* can be 0 so we store a copy */ 84 - BFS_I(inode)->i_sblock = di->i_sblock; 85 - BFS_I(inode)->i_eblock = di->i_eblock; 84 + BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */ 86 85 87 86 brelse(bh); 88 87 } 89 88 90 89 static int bfs_write_inode(struct inode * inode, int unused) 91 90 { 92 - unsigned long ino = inode->i_ino; 91 + unsigned int ino = (u16)inode->i_ino; 92 + unsigned long i_sblock; 93 93 struct bfs_inode * di; 94 94 struct buffer_head * bh; 95 95 int block, off; 96 96 97 + dprintf("ino=%08x\n", ino); 98 + 97 99 if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { 98 - printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); 100 + printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); 99 101 return -EIO; 100 102 } 101 103 ··· 107 101 block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; 108 102 bh = sb_bread(inode->i_sb, block); 109 103 if (!bh) { 110 - printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); 104 + printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino); 111 105 unlock_kernel(); 112 106 return -EIO; 113 107 } ··· 115 109 off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; 116 110 di = (struct bfs_inode *)bh->b_data + off; 117 111 118 - if (inode->i_ino == BFS_ROOT_INO) 119 - di->i_vtype = BFS_VDIR; 112 + if (ino == BFS_ROOT_INO) 113 + di->i_vtype = cpu_to_le32(BFS_VDIR); 120 114 else 121 - di->i_vtype = BFS_VREG; 115 + di->i_vtype = cpu_to_le32(BFS_VREG); 122 116 123 - di->i_ino = inode->i_ino; 124 - di->i_mode = inode->i_mode; 125 - di->i_uid = inode->i_uid; 126 - di->i_gid = inode->i_gid; 127 - di->i_nlink = inode->i_nlink; 128 - di->i_atime = inode->i_atime.tv_sec; 129 - di->i_mtime = inode->i_mtime.tv_sec; 130 - di->i_ctime = inode->i_ctime.tv_sec; 131 - di->i_sblock = BFS_I(inode)->i_sblock; 132 - di->i_eblock = BFS_I(inode)->i_eblock; 133 - di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1; 117 + di->i_ino = cpu_to_le16(ino); 118 + di->i_mode = cpu_to_le32(inode->i_mode); 119 + di->i_uid = cpu_to_le32(inode->i_uid); 120 + di->i_gid = cpu_to_le32(inode->i_gid); 121 + di->i_nlink = cpu_to_le32(inode->i_nlink); 122 + di->i_atime = cpu_to_le32(inode->i_atime.tv_sec); 123 + di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); 124 + di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); 125 + i_sblock = BFS_I(inode)->i_sblock; 126 + di->i_sblock = cpu_to_le32(i_sblock); 127 + di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock); 128 + di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); 134 129 135 130 mark_buffer_dirty(bh); 131 + dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off); 136 132 brelse(bh); 137 133 unlock_kernel(); 138 134 return 0; ··· 148 140 int block, off; 149 141 struct super_block * s = inode->i_sb; 150 142 struct bfs_sb_info * info = BFS_SB(s); 143 + struct bfs_inode_info * bi = BFS_I(inode); 151 144 152 - dprintf("ino=%08lx\n", inode->i_ino); 145 + dprintf("ino=%08lx\n", ino); 153 146 154 147 truncate_inode_pages(&inode->i_data, 0); 155 148 156 - if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > info->si_lasti) { 157 - printf("invalid ino=%08lx\n", inode->i_ino); 149 + if (ino < BFS_ROOT_INO || ino > info->si_lasti) { 150 + printf("invalid ino=%08lx\n", ino); 158 151 return; 159 152 } 160 153 ··· 171 162 return; 172 163 } 173 164 off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; 174 - di = (struct bfs_inode *)bh->b_data + off; 175 - if (di->i_ino) { 176 - info->si_freeb += BFS_FILEBLOCKS(di); 165 + di = (struct bfs_inode *) bh->b_data + off; 166 + if (bi->i_dsk_ino) { 167 + info->si_freeb += 1 + bi->i_eblock - bi->i_sblock; 177 168 info->si_freei++; 178 - clear_bit(di->i_ino, info->si_imap); 169 + clear_bit(ino, info->si_imap); 179 170 dump_imap("delete_inode", s); 180 - } 171 + } 181 172 di->i_ino = 0; 182 173 di->i_sblock = 0; 183 174 mark_buffer_dirty(bh); ··· 283 274 284 275 void dump_imap(const char *prefix, struct super_block * s) 285 276 { 286 - #if 0 277 + #ifdef DEBUG 287 278 int i; 288 279 char *tmpbuf = (char *)get_zeroed_page(GFP_KERNEL); 289 280 290 281 if (!tmpbuf) 291 282 return; 292 283 for (i=BFS_SB(s)->si_lasti; i>=0; i--) { 293 - if (i>PAGE_SIZE-100) break; 284 + if (i > PAGE_SIZE-100) break; 294 285 if (test_bit(i, BFS_SB(s)->si_imap)) 295 286 strcat(tmpbuf, "1"); 296 287 else ··· 306 297 struct buffer_head * bh; 307 298 struct bfs_super_block * bfs_sb; 308 299 struct inode * inode; 309 - int i, imap_len; 300 + unsigned i, imap_len; 310 301 struct bfs_sb_info * info; 311 302 312 303 info = kmalloc(sizeof(*info), GFP_KERNEL); ··· 321 312 if(!bh) 322 313 goto out; 323 314 bfs_sb = (struct bfs_super_block *)bh->b_data; 324 - if (bfs_sb->s_magic != BFS_MAGIC) { 315 + if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { 325 316 if (!silent) 326 317 printf("No BFS filesystem on %s (magic=%08x)\n", 327 - s->s_id, bfs_sb->s_magic); 318 + s->s_id, le32_to_cpu(bfs_sb->s_magic)); 328 319 goto out; 329 320 } 330 321 if (BFS_UNCLEAN(bfs_sb, s) && !silent) 331 322 printf("%s is unclean, continuing\n", s->s_id); 332 323 333 324 s->s_magic = BFS_MAGIC; 334 - info->si_bfs_sb = bfs_sb; 335 325 info->si_sbh = bh; 336 - info->si_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 326 + info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode) 337 327 + BFS_ROOT_INO - 1; 338 328 339 329 imap_len = info->si_lasti/8 + 1; ··· 356 348 goto out; 357 349 } 358 350 359 - info->si_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ 360 - info->si_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS; 351 + info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ 352 + info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - cpu_to_le32(bfs_sb->s_start))>>BFS_BSIZE_BITS; 361 353 info->si_freei = 0; 362 354 info->si_lf_eblk = 0; 363 355 info->si_lf_sblk = 0;
+12 -11
include/linux/bfs_fs.h
··· 14 14 #define BFS_INODES_PER_BLOCK 8 15 15 16 16 /* SVR4 vnode type values (bfs_inode->i_vtype) */ 17 - #define BFS_VDIR 2 18 - #define BFS_VREG 1 17 + #define BFS_VDIR 2L 18 + #define BFS_VREG 1L 19 + 19 20 20 21 /* BFS inode layout on disk */ 21 22 struct bfs_inode { ··· 59 58 __u32 s_padding[118]; 60 59 }; 61 60 62 - #define BFS_NZFILESIZE(ip) \ 63 - (((ip)->i_eoffset + 1) - (ip)->i_sblock * BFS_BSIZE) 64 - 65 - #define BFS_FILESIZE(ip) \ 66 - ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip)) 67 - 68 - #define BFS_FILEBLOCKS(ip) \ 69 - ((ip)->i_sblock == 0 ? 0 : ((ip)->i_eblock + 1) - (ip)->i_sblock) 70 61 71 62 #define BFS_OFF2INO(offset) \ 72 63 ((((offset) - BFS_BSIZE) / sizeof(struct bfs_inode)) + BFS_ROOT_INO) 73 64 74 65 #define BFS_INO2OFF(ino) \ 75 66 ((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE) 67 + #define BFS_NZFILESIZE(ip) \ 68 + ((cpu_to_le32((ip)->i_eoffset) + 1) - cpu_to_le32((ip)->i_sblock) * BFS_BSIZE) 76 69 70 + #define BFS_FILESIZE(ip) \ 71 + ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip)) 72 + 73 + #define BFS_FILEBLOCKS(ip) \ 74 + ((ip)->i_sblock == 0 ? 0 : (cpu_to_le32((ip)->i_eblock) + 1) - cpu_to_le32((ip)->i_sblock)) 77 75 #define BFS_UNCLEAN(bfs_sb, sb) \ 78 - ((bfs_sb->s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY)) 76 + ((cpu_to_le32(bfs_sb->s_from) != -1) && (cpu_to_le32(bfs_sb->s_to) != -1) && !(sb->s_flags & MS_RDONLY)) 77 + 79 78 80 79 #endif /* _LINUX_BFS_FS_H */