diff options
| -rw-r--r-- | fs/dcache.c | 11 | ||||
| -rw-r--r-- | fs/minix/bitmap.c | 55 | ||||
| -rw-r--r-- | fs/minix/inode.c | 25 | ||||
| -rw-r--r-- | fs/minix/minix.h | 11 |
4 files changed, 65 insertions, 37 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a901c6901bce..10ba92def3f6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/bit_spinlock.h> | 36 | #include <linux/bit_spinlock.h> |
| 37 | #include <linux/rculist_bl.h> | 37 | #include <linux/rculist_bl.h> |
| 38 | #include <linux/prefetch.h> | 38 | #include <linux/prefetch.h> |
| 39 | #include <linux/ratelimit.h> | ||
| 39 | #include "internal.h" | 40 | #include "internal.h" |
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| @@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
| 2383 | actual = __d_unalias(inode, dentry, alias); | 2384 | actual = __d_unalias(inode, dentry, alias); |
| 2384 | } | 2385 | } |
| 2385 | write_sequnlock(&rename_lock); | 2386 | write_sequnlock(&rename_lock); |
| 2386 | if (IS_ERR(actual)) | 2387 | if (IS_ERR(actual)) { |
| 2388 | if (PTR_ERR(actual) == -ELOOP) | ||
| 2389 | pr_warn_ratelimited( | ||
| 2390 | "VFS: Lookup of '%s' in %s %s" | ||
| 2391 | " would have caused loop\n", | ||
| 2392 | dentry->d_name.name, | ||
| 2393 | inode->i_sb->s_type->name, | ||
| 2394 | inode->i_sb->s_id); | ||
| 2387 | dput(alias); | 2395 | dput(alias); |
| 2396 | } | ||
| 2388 | goto out_nolock; | 2397 | goto out_nolock; |
| 2389 | } | 2398 | } |
| 2390 | } | 2399 | } |
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 3f32bcb0d9bd..ef175cb8cfd8 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c | |||
| @@ -16,38 +16,26 @@ | |||
| 16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
| 17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 18 | 18 | ||
| 19 | static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; | ||
| 20 | |||
| 21 | static DEFINE_SPINLOCK(bitmap_lock); | 19 | static DEFINE_SPINLOCK(bitmap_lock); |
| 22 | 20 | ||
| 23 | static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) | 21 | /* |
| 22 | * bitmap consists of blocks filled with 16bit words | ||
| 23 | * bit set == busy, bit clear == free | ||
| 24 | * endianness is a mess, but for counting zero bits it really doesn't matter... | ||
| 25 | */ | ||
| 26 | static __u32 count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits) | ||
| 24 | { | 27 | { |
| 25 | unsigned i, j, sum = 0; | 28 | __u32 sum = 0; |
| 26 | struct buffer_head *bh; | 29 | unsigned blocks = DIV_ROUND_UP(numbits, blocksize * 8); |
| 27 | |||
| 28 | for (i=0; i<numblocks-1; i++) { | ||
| 29 | if (!(bh=map[i])) | ||
| 30 | return(0); | ||
| 31 | for (j=0; j<bh->b_size; j++) | ||
| 32 | sum += nibblemap[bh->b_data[j] & 0xf] | ||
| 33 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | ||
| 34 | } | ||
| 35 | 30 | ||
| 36 | if (numblocks==0 || !(bh=map[numblocks-1])) | 31 | while (blocks--) { |
| 37 | return(0); | 32 | unsigned words = blocksize / 2; |
| 38 | i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; | 33 | __u16 *p = (__u16 *)(*map++)->b_data; |
| 39 | for (j=0; j<i; j++) { | 34 | while (words--) |
| 40 | sum += nibblemap[bh->b_data[j] & 0xf] | 35 | sum += 16 - hweight16(*p++); |
| 41 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | ||
| 42 | } | 36 | } |
| 43 | 37 | ||
| 44 | i = numbits%16; | 38 | return sum; |
| 45 | if (i!=0) { | ||
| 46 | i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1); | ||
| 47 | sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf]; | ||
| 48 | sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf]; | ||
| 49 | } | ||
| 50 | return(sum); | ||
| 51 | } | 39 | } |
| 52 | 40 | ||
| 53 | void minix_free_block(struct inode *inode, unsigned long block) | 41 | void minix_free_block(struct inode *inode, unsigned long block) |
| @@ -105,10 +93,12 @@ int minix_new_block(struct inode * inode) | |||
| 105 | return 0; | 93 | return 0; |
| 106 | } | 94 | } |
| 107 | 95 | ||
| 108 | unsigned long minix_count_free_blocks(struct minix_sb_info *sbi) | 96 | unsigned long minix_count_free_blocks(struct super_block *sb) |
| 109 | { | 97 | { |
| 110 | return (count_free(sbi->s_zmap, sbi->s_zmap_blocks, | 98 | struct minix_sb_info *sbi = minix_sb(sb); |
| 111 | sbi->s_nzones - sbi->s_firstdatazone + 1) | 99 | u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1); |
| 100 | |||
| 101 | return (count_free(sbi->s_zmap, sb->s_blocksize, bits) | ||
| 112 | << sbi->s_log_zone_size); | 102 | << sbi->s_log_zone_size); |
| 113 | } | 103 | } |
| 114 | 104 | ||
| @@ -273,7 +263,10 @@ struct inode *minix_new_inode(const struct inode *dir, int mode, int *error) | |||
| 273 | return inode; | 263 | return inode; |
| 274 | } | 264 | } |
| 275 | 265 | ||
| 276 | unsigned long minix_count_free_inodes(struct minix_sb_info *sbi) | 266 | unsigned long minix_count_free_inodes(struct super_block *sb) |
| 277 | { | 267 | { |
| 278 | return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1); | 268 | struct minix_sb_info *sbi = minix_sb(sb); |
| 269 | u32 bits = sbi->s_ninodes + 1; | ||
| 270 | |||
| 271 | return count_free(sbi->s_imap, sb->s_blocksize, bits); | ||
| 279 | } | 272 | } |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 64cdcd662ffc..1d9e33966db0 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
| @@ -279,6 +279,27 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
| 279 | else if (sbi->s_mount_state & MINIX_ERROR_FS) | 279 | else if (sbi->s_mount_state & MINIX_ERROR_FS) |
| 280 | printk("MINIX-fs: mounting file system with errors, " | 280 | printk("MINIX-fs: mounting file system with errors, " |
| 281 | "running fsck is recommended\n"); | 281 | "running fsck is recommended\n"); |
| 282 | |||
| 283 | /* Apparently minix can create filesystems that allocate more blocks for | ||
| 284 | * the bitmaps than needed. We simply ignore that, but verify it didn't | ||
| 285 | * create one with not enough blocks and bail out if so. | ||
| 286 | */ | ||
| 287 | block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); | ||
| 288 | if (sbi->s_imap_blocks < block) { | ||
| 289 | printk("MINIX-fs: file system does not have enough " | ||
| 290 | "imap blocks allocated. Refusing to mount\n"); | ||
| 291 | goto out_iput; | ||
| 292 | } | ||
| 293 | |||
| 294 | block = minix_blocks_needed( | ||
| 295 | (sbi->s_nzones - (sbi->s_firstdatazone + 1)), | ||
| 296 | s->s_blocksize); | ||
| 297 | if (sbi->s_zmap_blocks < block) { | ||
| 298 | printk("MINIX-fs: file system does not have enough " | ||
| 299 | "zmap blocks allocated. Refusing to mount.\n"); | ||
| 300 | goto out_iput; | ||
| 301 | } | ||
| 302 | |||
| 282 | return 0; | 303 | return 0; |
| 283 | 304 | ||
| 284 | out_iput: | 305 | out_iput: |
| @@ -339,10 +360,10 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 339 | buf->f_type = sb->s_magic; | 360 | buf->f_type = sb->s_magic; |
| 340 | buf->f_bsize = sb->s_blocksize; | 361 | buf->f_bsize = sb->s_blocksize; |
| 341 | buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; | 362 | buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; |
| 342 | buf->f_bfree = minix_count_free_blocks(sbi); | 363 | buf->f_bfree = minix_count_free_blocks(sb); |
| 343 | buf->f_bavail = buf->f_bfree; | 364 | buf->f_bavail = buf->f_bfree; |
| 344 | buf->f_files = sbi->s_ninodes; | 365 | buf->f_files = sbi->s_ninodes; |
| 345 | buf->f_ffree = minix_count_free_inodes(sbi); | 366 | buf->f_ffree = minix_count_free_inodes(sb); |
| 346 | buf->f_namelen = sbi->s_namelen; | 367 | buf->f_namelen = sbi->s_namelen; |
| 347 | buf->f_fsid.val[0] = (u32)id; | 368 | buf->f_fsid.val[0] = (u32)id; |
| 348 | buf->f_fsid.val[1] = (u32)(id >> 32); | 369 | buf->f_fsid.val[1] = (u32)(id >> 32); |
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 341e2122879a..26bbd55e82ea 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
| @@ -48,10 +48,10 @@ extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, stru | |||
| 48 | extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **); | 48 | extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **); |
| 49 | extern struct inode * minix_new_inode(const struct inode *, int, int *); | 49 | extern struct inode * minix_new_inode(const struct inode *, int, int *); |
| 50 | extern void minix_free_inode(struct inode * inode); | 50 | extern void minix_free_inode(struct inode * inode); |
| 51 | extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi); | 51 | extern unsigned long minix_count_free_inodes(struct super_block *sb); |
| 52 | extern int minix_new_block(struct inode * inode); | 52 | extern int minix_new_block(struct inode * inode); |
| 53 | extern void minix_free_block(struct inode *inode, unsigned long block); | 53 | extern void minix_free_block(struct inode *inode, unsigned long block); |
| 54 | extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi); | 54 | extern unsigned long minix_count_free_blocks(struct super_block *sb); |
| 55 | extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 55 | extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
| 56 | extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len); | 56 | extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len); |
| 57 | 57 | ||
| @@ -88,6 +88,11 @@ static inline struct minix_inode_info *minix_i(struct inode *inode) | |||
| 88 | return list_entry(inode, struct minix_inode_info, vfs_inode); | 88 | return list_entry(inode, struct minix_inode_info, vfs_inode); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksize) | ||
| 92 | { | ||
| 93 | return DIV_ROUND_UP(bits, blocksize * 8); | ||
| 94 | } | ||
| 95 | |||
| 91 | #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \ | 96 | #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \ |
| 92 | defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) | 97 | defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) |
| 93 | 98 | ||
| @@ -125,7 +130,7 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size) | |||
| 125 | if (!size) | 130 | if (!size) |
| 126 | return 0; | 131 | return 0; |
| 127 | 132 | ||
| 128 | size = (size >> 4) + ((size & 15) > 0); | 133 | size >>= 4; |
| 129 | while (*p++ == 0xffff) { | 134 | while (*p++ == 0xffff) { |
| 130 | if (--size == 0) | 135 | if (--size == 0) |
| 131 | return (p - addr) << 4; | 136 | return (p - addr) << 4; |
