brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · 269df6d Raw
236 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  linux/fs/sysv/ialloc.c4 *5 *  minix/bitmap.c6 *  Copyright (C) 1991, 1992  Linus Torvalds7 *8 *  ext/freelists.c9 *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)10 *11 *  xenix/alloc.c12 *  Copyright (C) 1992  Doug Evans13 *14 *  coh/alloc.c15 *  Copyright (C) 1993  Pascal Haible, Bruno Haible16 *17 *  sysv/ialloc.c18 *  Copyright (C) 1993  Bruno Haible19 *20 *  This file contains code for allocating/freeing inodes.21 */22 23#include <linux/kernel.h>24#include <linux/stddef.h>25#include <linux/sched.h>26#include <linux/stat.h>27#include <linux/string.h>28#include <linux/buffer_head.h>29#include <linux/writeback.h>30#include "sysv.h"31 32/* We don't trust the value of33   sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes34   but we nevertheless keep it up to date. */35 36/* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */37 38/* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */39static inline sysv_ino_t *40sv_sb_fic_inode(struct super_block * sb, unsigned int i)41{42	struct sysv_sb_info *sbi = SYSV_SB(sb);43 44	if (sbi->s_bh1 == sbi->s_bh2)45		return &sbi->s_sb_fic_inodes[i];46	else {47		/* 512 byte Xenix FS */48		unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);49		if (offset < 512)50			return (sysv_ino_t*)(sbi->s_sbd1 + offset);51		else52			return (sysv_ino_t*)(sbi->s_sbd2 + offset);53	}54}55 56struct sysv_inode *57sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh)58{59	struct sysv_sb_info *sbi = SYSV_SB(sb);60	struct sysv_inode *res;61	int block = sbi->s_firstinodezone + sbi->s_block_base;62 63	block += (ino-1) >> sbi->s_inodes_per_block_bits;64	*bh = sb_bread(sb, block);65	if (!*bh)66		return NULL;67	res = (struct sysv_inode *)(*bh)->b_data;68	return res + ((ino-1) & sbi->s_inodes_per_block_1);69}70 71static int refill_free_cache(struct super_block *sb)72{73	struct sysv_sb_info *sbi = SYSV_SB(sb);74	struct buffer_head * bh;75	struct sysv_inode * raw_inode;76	int i = 0, ino;77 78	ino = SYSV_ROOT_INO+1;79	raw_inode = sysv_raw_inode(sb, ino, &bh);80	if (!raw_inode)81		goto out;82	while (ino <= sbi->s_ninodes) {83		if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) {84			*sv_sb_fic_inode(sb,i++) = cpu_to_fs16(SYSV_SB(sb), ino);85			if (i == sbi->s_fic_size)86				break;87		}88		if ((ino++ & sbi->s_inodes_per_block_1) == 0) {89			brelse(bh);90			raw_inode = sysv_raw_inode(sb, ino, &bh);91			if (!raw_inode)92				goto out;93		} else94			raw_inode++;95	}96	brelse(bh);97out:98	return i;99}100 101void sysv_free_inode(struct inode * inode)102{103	struct super_block *sb = inode->i_sb;104	struct sysv_sb_info *sbi = SYSV_SB(sb);105	unsigned int ino;106	struct buffer_head * bh;107	struct sysv_inode * raw_inode;108	unsigned count;109 110	sb = inode->i_sb;111	ino = inode->i_ino;112	if (ino <= SYSV_ROOT_INO || ino > sbi->s_ninodes) {113		printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");114		return;115	}116	raw_inode = sysv_raw_inode(sb, ino, &bh);117	if (!raw_inode) {118		printk("sysv_free_inode: unable to read inode block on device "119		       "%s\n", inode->i_sb->s_id);120		return;121	}122	mutex_lock(&sbi->s_lock);123	count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);124	if (count < sbi->s_fic_size) {125		*sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino);126		*sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);127	}128	fs16_add(sbi, sbi->s_sb_total_free_inodes, 1);129	dirty_sb(sb);130	memset(raw_inode, 0, sizeof(struct sysv_inode));131	mark_buffer_dirty(bh);132	mutex_unlock(&sbi->s_lock);133	brelse(bh);134}135 136struct inode * sysv_new_inode(const struct inode * dir, umode_t mode)137{138	struct super_block *sb = dir->i_sb;139	struct sysv_sb_info *sbi = SYSV_SB(sb);140	struct inode *inode;141	sysv_ino_t ino;142	unsigned count;143	struct writeback_control wbc = {144		.sync_mode = WB_SYNC_NONE145	};146 147	inode = new_inode(sb);148	if (!inode)149		return ERR_PTR(-ENOMEM);150 151	mutex_lock(&sbi->s_lock);152	count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);153	if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {154		count = refill_free_cache(sb);155		if (count == 0) {156			iput(inode);157			mutex_unlock(&sbi->s_lock);158			return ERR_PTR(-ENOSPC);159		}160	}161	/* Now count > 0. */162	ino = *sv_sb_fic_inode(sb,--count);163	*sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);164	fs16_add(sbi, sbi->s_sb_total_free_inodes, -1);165	dirty_sb(sb);166	inode_init_owner(&nop_mnt_idmap, inode, dir, mode);167	inode->i_ino = fs16_to_cpu(sbi, ino);168	simple_inode_init_ts(inode);169	inode->i_blocks = 0;170	memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));171	SYSV_I(inode)->i_dir_start_lookup = 0;172	insert_inode_hash(inode);173	mark_inode_dirty(inode);174 175	sysv_write_inode(inode, &wbc);	/* ensure inode not allocated again */176	mark_inode_dirty(inode);	/* cleared by sysv_write_inode() */177	/* That's it. */178	mutex_unlock(&sbi->s_lock);179	return inode;180}181 182unsigned long sysv_count_free_inodes(struct super_block * sb)183{184	struct sysv_sb_info *sbi = SYSV_SB(sb);185	struct buffer_head * bh;186	struct sysv_inode * raw_inode;187	int ino, count, sb_count;188 189	mutex_lock(&sbi->s_lock);190 191	sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes);192 193	if (0)194		goto trust_sb;195 196	/* this causes a lot of disk traffic ... */197	count = 0;198	ino = SYSV_ROOT_INO+1;199	raw_inode = sysv_raw_inode(sb, ino, &bh);200	if (!raw_inode)201		goto Eio;202	while (ino <= sbi->s_ninodes) {203		if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)204			count++;205		if ((ino++ & sbi->s_inodes_per_block_1) == 0) {206			brelse(bh);207			raw_inode = sysv_raw_inode(sb, ino, &bh);208			if (!raw_inode)209				goto Eio;210		} else211			raw_inode++;212	}213	brelse(bh);214	if (count != sb_count)215		goto Einval;216out:217	mutex_unlock(&sbi->s_lock);218	return count;219 220Einval:221	printk("sysv_count_free_inodes: "222		"free inode count was %d, correcting to %d\n",223		sb_count, count);224	if (!sb_rdonly(sb)) {225		*sbi->s_sb_total_free_inodes = cpu_to_fs16(SYSV_SB(sb), count);226		dirty_sb(sb);227	}228	goto out;229 230Eio:231	printk("sysv_count_free_inodes: unable to read inode table\n");232trust_sb:233	count = sb_count;234	goto out;235}236