Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 939b00df authored by Andries Brouwer's avatar Andries Brouwer Committed by Linus Torvalds
Browse files

[PATCH] Minix V3 support

This morning I needed to read a Minix V3 filesystem, but unfortunately my
2.6.19 did not support that, and neither did the downloaded 2.6.20rc4.

Fortunately, google told me that Daniel Aragones had already done the work,
patch found at http://www.terra.es/personal2/danarag/



Unfortunaly, looking at the patch was painful to my eyes, so I polished it
a bit before applying.  The resulting kernel boots, and reads the
filesystem it needed to read.

Signed-off-by: default avatarDaniel Aragones <danarag@gmail.com>
Signed-off-by: default avatarAndries Brouwer <aeb@cwi.nl>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b587b13a
Loading
Loading
Loading
Loading
+40 −29
Original line number Diff line number Diff line
@@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
	for (i=0; i<numblocks-1; i++) {
		if (!(bh=map[i])) 
			return(0);
		for (j=0; j<BLOCK_SIZE; j++)
		for (j=0; j<bh->b_size; j++)
			sum += nibblemap[bh->b_data[j] & 0xf]
				+ nibblemap[(bh->b_data[j]>>4) & 0xf];
	}

	if (numblocks==0 || !(bh=map[numblocks-1]))
		return(0);
	i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
	i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
	for (j=0; j<i; j++) {
		sum += nibblemap[bh->b_data[j] & 0xf]
			+ nibblemap[(bh->b_data[j]>>4) & 0xf];
@@ -48,20 +48,21 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
	return(sum);
}

void minix_free_block(struct inode * inode, int block)
void minix_free_block(struct inode *inode, unsigned long block)
{
	struct super_block *sb = inode->i_sb;
	struct minix_sb_info *sbi = minix_sb(sb);
	struct buffer_head *bh;
	unsigned int bit,zone;
	int k = sb->s_blocksize_bits + 3;
	unsigned long bit, zone;

	if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
		printk("Trying to free block not in datazone\n");
		return;
	}
	zone = block - sbi->s_firstdatazone + 1;
	bit = zone & 8191;
	zone >>= 13;
	bit = zone & ((1<<k) - 1);
	zone >>= k;
	if (zone >= sbi->s_zmap_blocks) {
		printk("minix_free_block: nonexistent bitmap buffer\n");
		return;
@@ -69,7 +70,7 @@ void minix_free_block(struct inode * inode, int block)
	bh = sbi->s_zmap[zone];
	lock_kernel();
	if (!minix_test_and_clear_bit(bit, bh->b_data))
		printk("free_block (%s:%d): bit already cleared\n",
		printk("minix_free_block (%s:%lu): bit already cleared\n",
		       sb->s_id, block);
	unlock_kernel();
	mark_buffer_dirty(bh);
@@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block)
int minix_new_block(struct inode * inode)
{
	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
	int bits_per_zone = 8 * inode->i_sb->s_blocksize;
	int i;

	for (i = 0; i < sbi->s_zmap_blocks; i++) {
@@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode)
		int j;

		lock_kernel();
		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
		if (j < bits_per_zone) {
			minix_set_bit(j, bh->b_data);
			unlock_kernel();
			mark_buffer_dirty(bh);
			j += i*8192 + sbi->s_firstdatazone-1;
			j += i * bits_per_zone + sbi->s_firstdatazone-1;
			if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
				break;
			return j;
@@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
	int block;
	struct minix_sb_info *sbi = minix_sb(sb);
	struct minix2_inode *p;
	int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);

	*bh = NULL;
	if (!ino || ino > sbi->s_ninodes) {
@@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
	}
	ino--;
	block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
		 ino / MINIX2_INODES_PER_BLOCK;
		 ino / minix2_inodes_per_block;
	*bh = sb_bread(sb, block);
	if (!*bh) {
		printk("Unable to read inode block\n");
		return NULL;
	}
	p = (void *)(*bh)->b_data;
	return p + ino % MINIX2_INODES_PER_BLOCK;
	return p + ino % minix2_inodes_per_block;
}

/* Clear the link count and mode of a deleted inode on disk. */
@@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode)

void minix_free_inode(struct inode * inode)
{
	struct super_block *sb = inode->i_sb;
	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
	struct buffer_head *bh;
	unsigned long ino;
	int k = sb->s_blocksize_bits + 3;
	unsigned long ino, bit;

	ino = inode->i_ino;
	if (ino < 1 || ino > sbi->s_ninodes) {
		printk("minix_free_inode: inode 0 or nonexistent inode\n");
		goto out;
	}
	if ((ino >> 13) >= sbi->s_imap_blocks) {
	bit = ino & ((1<<k) - 1);
	ino >>= k;
	if (ino >= sbi->s_imap_blocks) {
		printk("minix_free_inode: nonexistent imap in superblock\n");
		goto out;
	}

	minix_clear_inode(inode);	/* clear on-disk copy */

	bh = sbi->s_imap[ino >> 13];
	bh = sbi->s_imap[ino];
	lock_kernel();
	if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
		printk("minix_free_inode: bit %lu already cleared\n", ino);
	if (!minix_test_and_clear_bit(bit, bh->b_data))
		printk("minix_free_inode: bit %lu already cleared\n", bit);
	unlock_kernel();
	mark_buffer_dirty(bh);
 out:
@@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
	struct minix_sb_info *sbi = minix_sb(sb);
	struct inode *inode = new_inode(sb);
	struct buffer_head * bh;
	int i,j;
	int bits_per_zone = 8 * sb->s_blocksize;
	unsigned long j;
	int i;

	if (!inode) {
		*error = -ENOMEM;
		return NULL;
	}
	j = 8192;
	j = bits_per_zone;
	bh = NULL;
	*error = -ENOSPC;
	lock_kernel();
	for (i = 0; i < sbi->s_imap_blocks; i++) {
		bh = sbi->s_imap[i];
		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
		if (j < bits_per_zone)
			break;
	}
	if (!bh || j >= 8192) {
	if (!bh || j >= bits_per_zone) {
		unlock_kernel();
		iput(inode);
		return NULL;
	}
	if (minix_test_and_set_bit(j, bh->b_data)) {	/* shouldn't happen */
		printk("new_inode: bit already set\n");
		unlock_kernel();
		printk("minix_new_inode: bit already set\n");
		iput(inode);
		return NULL;
	}
	unlock_kernel();
	mark_buffer_dirty(bh);
	j += i*8192;
	j += i * bits_per_zone;
	if (!j || j > sbi->s_ninodes) {
		iput(inode);
		return NULL;
+111 −51
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
 *  Copyright (C) 1991, 1992 Linus Torvalds
 *
 *  minix directory handling functions
 *
 *  Updated to filesystem version 3 by Daniel Aragones
 */

#include "minix.h"
@@ -11,6 +13,7 @@
#include <linux/smp_lock.h>

typedef struct minix_dir_entry minix_dirent;
typedef struct minix3_dir_entry minix3_dirent;

static int minix_readdir(struct file *, void *, filldir_t);

@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
	unsigned long npages = dir_pages(inode);
	struct minix_sb_info *sbi = minix_sb(sb);
	unsigned chunk_size = sbi->s_dirsize;
	char *name;
	__u32 inumber;

	lock_kernel();

@@ -106,15 +111,23 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
		p = kaddr+offset;
		limit = kaddr + minix_last_byte(inode, n) - chunk_size;
		for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
			if (sbi->s_version == MINIX_V3) {
				minix3_dirent *de3 = (minix3_dirent *)p;
				name = de3->name;
				inumber = de3->inode;
	 		} else {
				minix_dirent *de = (minix_dirent *)p;
			if (de->inode) {
				name = de->name;
				inumber = de->inode;
			}
			if (inumber) {
				int over;
				unsigned l = strnlen(de->name,sbi->s_namelen);

				unsigned l = strnlen(name, sbi->s_namelen);
				offset = p - kaddr;
				over = filldir(dirent, de->name, l,
				over = filldir(dirent, name, l,
					(n << PAGE_CACHE_SHIFT) | offset,
						de->inode, DT_UNKNOWN);
					inumber, DT_UNKNOWN);
				if (over) {
					dir_put_page(page);
					goto done;
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
	unsigned long n;
	unsigned long npages = dir_pages(dir);
	struct page *page = NULL;
	struct minix_dir_entry *de;
	char *p;

	char *namx;
	__u32 inumber;
	*res_page = NULL;

	for (n = 0; n < npages; n++) {
		char *kaddr;
		char *kaddr, *limit;

		page = dir_get_page(dir, n);
		if (IS_ERR(page))
			continue;

		kaddr = (char*)page_address(page);
		de = (struct minix_dir_entry *) kaddr;
		kaddr += minix_last_byte(dir, n) - sbi->s_dirsize;
		for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
			if (!de->inode)
		limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
			if (sbi->s_version == MINIX_V3) {
				minix3_dirent *de3 = (minix3_dirent *)p;
				namx = de3->name;
				inumber = de3->inode;
 			} else {
				minix_dirent *de = (minix_dirent *)p;
				namx = de->name;
				inumber = de->inode;
			}
			if (!inumber)
				continue;
			if (namecompare(namelen,sbi->s_namelen,name,de->name))
			if (namecompare(namelen, sbi->s_namelen, name, namx))
				goto found;
		}
		dir_put_page(page);
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)

found:
	*res_page = page;
	return de;
	return (minix_dirent *)p;
}

int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
	struct super_block * sb = dir->i_sb;
	struct minix_sb_info * sbi = minix_sb(sb);
	struct page *page = NULL;
	struct minix_dir_entry * de;
	unsigned long npages = dir_pages(dir);
	unsigned long n;
	char *kaddr;
	char *kaddr, *p;
	minix_dirent *de;
	minix3_dirent *de3;
	unsigned from, to;
	int err;
	char *namx = NULL;
	__u32 inumber;

	/*
	 * We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
	 * to protect that region.
	 */
	for (n = 0; n <= npages; n++) {
		char *dir_end;
		char *limit, *dir_end;

		page = dir_get_page(dir, n);
		err = PTR_ERR(page);
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
		lock_page(page);
		kaddr = (char*)page_address(page);
		dir_end = kaddr + minix_last_byte(dir, n);
		de = (minix_dirent *)kaddr;
		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
		while ((char *)de <= kaddr) {
			if ((char *)de == dir_end) {
		limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
			de = (minix_dirent *)p;
			de3 = (minix3_dirent *)p;
			if (sbi->s_version == MINIX_V3) {
				namx = de3->name;
				inumber = de3->inode;
		 	} else {
  				namx = de->name;
				inumber = de->inode;
			}
			if (p == dir_end) {
				/* We hit i_size */
				if (sbi->s_version == MINIX_V3)
					de3->inode = 0;
		 		else
					de->inode = 0;
				goto got_it;
			}
			if (!de->inode)
			if (!inumber)
				goto got_it;
			err = -EEXIST;
			if (namecompare(namelen,sbi->s_namelen,name,de->name))
			if (namecompare(namelen, sbi->s_namelen, name, namx))
				goto out_unlock;
			de = minix_next_entry(de, sbi);
		}
		unlock_page(page);
		dir_put_page(page);
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
	return -EINVAL;

got_it:
	from = (char*)de - (char*)page_address(page);
	from = p - (char*)page_address(page);
	to = from + sbi->s_dirsize;
	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
	if (err)
		goto out_unlock;
	memcpy (de->name, name, namelen);
	memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
	memcpy (namx, name, namelen);
	if (sbi->s_version == MINIX_V3) {
		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
		de3->inode = inode->i_ino;
	} else {
		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
		de->inode = inode->i_ino;
	}
	err = dir_commit_chunk(page, from, to);
	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(dir);
@@ -284,7 +326,6 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
	struct address_space *mapping = inode->i_mapping;
	struct page *page = grab_cache_page(mapping, 0);
	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
	struct minix_dir_entry * de;
	char *kaddr;
	int err;

@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
	kaddr = kmap_atomic(page, KM_USER0);
	memset(kaddr, 0, PAGE_CACHE_SIZE);

	de = (struct minix_dir_entry *)kaddr;
	if (sbi->s_version == MINIX_V3) {
		minix3_dirent *de3 = (minix3_dirent *)kaddr;

		de3->inode = inode->i_ino;
		strcpy(de3->name, ".");
		de3 = minix_next_entry(de3, sbi);
		de3->inode = dir->i_ino;
		strcpy(de3->name, "..");
	} else {
		minix_dirent *de = (minix_dirent *)kaddr;

		de->inode = inode->i_ino;
		strcpy(de->name, ".");
		de = minix_next_entry(de, sbi);
		de->inode = dir->i_ino;
		strcpy(de->name, "..");
	}
	kunmap_atomic(kaddr, KM_USER0);

	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode)
	struct page *page = NULL;
	unsigned long i, npages = dir_pages(inode);
	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
	char *name;
	__u32 inumber;

	for (i = 0; i < npages; i++) {
		char *kaddr;
		minix_dirent * de;
		page = dir_get_page(inode, i);
		char *p, *kaddr, *limit;

		page = dir_get_page(inode, i);
		if (IS_ERR(page))
			continue;

		kaddr = (char *)page_address(page);
		de = (minix_dirent *)kaddr;
		kaddr += minix_last_byte(inode, i) - sbi->s_dirsize;
		limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
			if (sbi->s_version == MINIX_V3) {
				minix3_dirent *de3 = (minix3_dirent *)p;
				name = de3->name;
				inumber = de3->inode;
			} else {
				minix_dirent *de = (minix_dirent *)p;
				name = de->name;
				inumber = de->inode;
			}

		while ((char *)de <= kaddr) {
			if (de->inode != 0) {
			if (inumber != 0) {
				/* check for . and .. */
				if (de->name[0] != '.')
				if (name[0] != '.')
					goto not_empty;
				if (!de->name[1]) {
					if (de->inode != inode->i_ino)
				if (!name[1]) {
					if (inumber != inode->i_ino)
						goto not_empty;
				} else if (de->name[1] != '.')
				} else if (name[1] != '.')
					goto not_empty;
				else if (de->name[2])
				else if (name[2])
					goto not_empty;
			}
			de = minix_next_entry(de, sbi);
		}
		dir_put_page(page);
	}
+38 −11
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 *	Minix V2 fs support.
 *
 *  Modified for 680x0 by Andreas Schwab
 *  Updated to filesystem version 3 by Daniel Aragones
 */

#include <linux/module.h>
@@ -36,6 +37,7 @@ static void minix_put_super(struct super_block *sb)
	struct minix_sb_info *sbi = minix_sb(sb);

	if (!(sb->s_flags & MS_RDONLY)) {
		if (sbi->s_version != MINIX_V3)	 /* s_state is now out from V3 sb */
			sbi->s_ms->s_state = sbi->s_mount_state;
		mark_buffer_dirty(sbi->s_sbh);
	}
@@ -117,12 +119,17 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
		    !(sbi->s_mount_state & MINIX_VALID_FS))
			return 0;
		/* Mounting a rw partition read-only. */
		if (sbi->s_version != MINIX_V3)
			ms->s_state = sbi->s_mount_state;
		mark_buffer_dirty(sbi->s_sbh);
	} else {
	  	/* Mount a partition which is read-only, read-write. */
		if (sbi->s_version != MINIX_V3) {
			sbi->s_mount_state = ms->s_state;
			ms->s_state &= ~MINIX_VALID_FS;
		} else {
			sbi->s_mount_state = MINIX_VALID_FS;
		}
		mark_buffer_dirty(sbi->s_sbh);

		if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -140,7 +147,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
	struct buffer_head *bh;
	struct buffer_head **map;
	struct minix_super_block *ms;
	int i, block;
	struct minix3_super_block *m3s = NULL;
	unsigned long i, block;
	struct inode *root_inode;
	struct minix_sb_info *sbi;

@@ -192,6 +200,22 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
		m3s = (struct minix3_super_block *) bh->b_data;
		s->s_magic = m3s->s_magic;
		sbi->s_imap_blocks = m3s->s_imap_blocks;
		sbi->s_zmap_blocks = m3s->s_zmap_blocks;
		sbi->s_firstdatazone = m3s->s_firstdatazone;
		sbi->s_log_zone_size = m3s->s_log_zone_size;
		sbi->s_max_size = m3s->s_max_size;
		sbi->s_ninodes = m3s->s_ninodes;
		sbi->s_nzones = m3s->s_zones;
		sbi->s_dirsize = 64;
		sbi->s_namelen = 60;
		sbi->s_version = MINIX_V3;
		sbi->s_link_max = MINIX2_LINK_MAX;
		sbi->s_mount_state = MINIX_VALID_FS;
		sb_set_blocksize(s, m3s->s_blocksize);
	} else
		goto out_no_fs;

@@ -236,6 +260,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
		s->s_root->d_op = &minix_dentry_operations;

	if (!(s->s_flags & MS_RDONLY)) {
		if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
			ms->s_state &= ~MINIX_VALID_FS;
		mark_buffer_dirty(bh);
	}
@@ -278,8 +303,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)

out_no_fs:
	if (!silent)
		printk("VFS: Can't find a Minix or Minix V2 filesystem "
			"on device %s\n", s->s_id);
		printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
		       "on device %s.\n", s->s_id);
out_release:
	brelse(bh);
	goto out;
@@ -537,12 +562,14 @@ int minix_sync_inode(struct inode * inode)

int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
	struct inode *dir = dentry->d_parent->d_inode;
	struct super_block *sb = dir->i_sb;
	generic_fillattr(dentry->d_inode, stat);
	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
	else
		stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size);
	stat->blksize = BLOCK_SIZE;
		stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
	stat->blksize = sb->s_blocksize;
	return 0;
}

+9 −7
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ static inline int verify_chain(Indirect *from, Indirect *to)

static inline block_t *block_end(struct buffer_head *bh)
{
	return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
	return (block_t *)((char*)bh->b_data + bh->b_size);
}

static inline Indirect *get_branch(struct inode *inode,
@@ -85,7 +85,7 @@ static int alloc_branch(struct inode *inode,
		branch[n].key = cpu_to_block(nr);
		bh = sb_getblk(inode->i_sb, parent);
		lock_buffer(bh);
		memset(bh->b_data, 0, BLOCK_SIZE);
		memset(bh->b_data, 0, bh->b_size);
		branch[n].bh = bh;
		branch[n].p = (block_t*) bh->b_data + offsets[n];
		*branch[n].p = branch[n].key;
@@ -292,6 +292,7 @@ static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth

static inline void truncate (struct inode * inode)
{
	struct super_block *sb = inode->i_sb;
	block_t *idata = i_data(inode);
	int offsets[DEPTH];
	Indirect chain[DEPTH];
@@ -301,7 +302,7 @@ static inline void truncate (struct inode * inode)
	int first_whole;
	long iblock;

	iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
	iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits;
	block_truncate_page(inode->i_mapping, inode->i_size, get_block);

	n = block_to_path(inode, iblock, offsets);
@@ -346,15 +347,16 @@ static inline void truncate (struct inode * inode)
	mark_inode_dirty(inode);
}

static inline unsigned nblocks(loff_t size)
static inline unsigned nblocks(loff_t size, struct super_block *sb)
{
	int k = sb->s_blocksize_bits - 10;
	unsigned blocks, res, direct = DIRECT, i = DEPTH;
	blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
	blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k);
	res = blocks;
	while (--i && blocks > direct) {
		blocks -= direct;
		blocks += BLOCK_SIZE/sizeof(block_t) - 1;
		blocks /= BLOCK_SIZE/sizeof(block_t);
		blocks += sb->s_blocksize/sizeof(block_t) - 1;
		blocks /= sb->s_blocksize/sizeof(block_t);
		res += blocks;
		direct = 1;
	}
+2 −2
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ void V1_minix_truncate(struct inode * inode)
	truncate(inode);
}

unsigned V1_minix_blocks(loff_t size)
unsigned V1_minix_blocks(loff_t size, struct super_block *sb)
{
	return nblocks(size);
	return nblocks(size, sb);
}
Loading