cregit-Linux how code gets into the kernel

Release 4.11 fs/sysv/balloc.c

Directory: fs/sysv
/*
 *  linux/fs/sysv/balloc.c
 *
 *  minix/bitmap.c
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  ext/freelists.c
 *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
 *
 *  xenix/alloc.c
 *  Copyright (C) 1992  Doug Evans
 *
 *  coh/alloc.c
 *  Copyright (C) 1993  Pascal Haible, Bruno Haible
 *
 *  sysv/balloc.c
 *  Copyright (C) 1993  Bruno Haible
 *
 *  This file contains code for allocating/freeing blocks.
 */

#include <linux/buffer_head.h>
#include <linux/string.h>
#include "sysv.h"

/* We don't trust the value of
   sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
   but we nevertheless keep it up to date. */


static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh) { char *bh_data = bh->b_data; if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4) return (sysv_zone_t*)(bh_data+4); else return (sysv_zone_t*)(bh_data+2); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3558.33%125.00%
Linus Torvalds (pre-git)1830.00%125.00%
Christoph Hellwig46.67%125.00%
Al Viro35.00%125.00%
Total60100.00%4100.00%

/* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
void sysv_free_block(struct super_block * sb, sysv_zone_t nr) { struct sysv_sb_info * sbi = SYSV_SB(sb); struct buffer_head * bh; sysv_zone_t *blocks = sbi->s_bcache; unsigned count; unsigned block = fs32_to_cpu(sbi, nr); /* * This code does not work at all for AFS (it has a bitmap * free list). As AFS is supposed to be read-only no one * should call this for an AFS filesystem anyway... */ if (sbi->s_type == FSTYPE_AFS) return; if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { printk("sysv_free_block: trying to free block not in datazone\n"); return; } mutex_lock(&sbi->s_lock); count = fs16_to_cpu(sbi, *sbi->s_bcache_count); if (count > sbi->s_flc_size) { printk("sysv_free_block: flc_count > flc_size\n"); mutex_unlock(&sbi->s_lock); return; } /* If the free list head in super-block is full, it is copied * into this block being freed, ditto if it's completely empty * (applies only on Coherent). */ if (count == sbi->s_flc_size || count == 0) { block += sbi->s_block_base; bh = sb_getblk(sb, block); if (!bh) { printk("sysv_free_block: getblk() failed\n"); mutex_unlock(&sbi->s_lock); return; } memset(bh->b_data, 0, sb->s_blocksize); *(__fs16*)bh->b_data = cpu_to_fs16(sbi, count); memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t)); mark_buffer_dirty(bh); set_buffer_uptodate(bh); brelse(bh); count = 0; } sbi->s_bcache[count++] = nr; *sbi->s_bcache_count = cpu_to_fs16(sbi, count); fs32_add(sbi, sbi->s_free_blocks, 1); dirty_sb(sb); mutex_unlock(&sbi->s_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13747.40%541.67%
Linus Torvalds9131.49%325.00%
Christoph Hellwig3712.80%18.33%
Marco Stornelli206.92%18.33%
Al Viro31.04%18.33%
Andrew Morton10.35%18.33%
Total289100.00%12100.00%


sysv_zone_t sysv_new_block(struct super_block * sb) { struct sysv_sb_info *sbi = SYSV_SB(sb); unsigned int block; sysv_zone_t nr; struct buffer_head * bh; unsigned count; mutex_lock(&sbi->s_lock); count = fs16_to_cpu(sbi, *sbi->s_bcache_count); if (count == 0) /* Applies only to Coherent FS */ goto Enospc; nr = sbi->s_bcache[--count]; if (nr == 0) /* Applies only to Xenix FS, SystemV FS */ goto Enospc; block = fs32_to_cpu(sbi, nr); *sbi->s_bcache_count = cpu_to_fs16(sbi, count); if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { printk("sysv_new_block: new block %d is not in data zone\n", block); goto Enospc; } if (count == 0) { /* the last block continues the free list */ unsigned count; block += sbi->s_block_base; if (!(bh = sb_bread(sb, block))) { printk("sysv_new_block: cannot read free-list block\n"); /* retry this same block next time */ *sbi->s_bcache_count = cpu_to_fs16(sbi, 1); goto Enospc; } count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data); if (count > sbi->s_flc_size) { printk("sysv_new_block: free-list block with >flc_size entries\n"); brelse(bh); goto Enospc; } *sbi->s_bcache_count = cpu_to_fs16(sbi, count); memcpy(sbi->s_bcache, get_chunk(sb, bh), count * sizeof(sysv_zone_t)); brelse(bh); } /* Now the free list head in the superblock is valid again. */ fs32_add(sbi, sbi->s_free_blocks, -1); dirty_sb(sb); mutex_unlock(&sbi->s_lock); return nr; Enospc: mutex_unlock(&sbi->s_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)16955.23%228.57%
Linus Torvalds8026.14%228.57%
Christoph Hellwig3912.75%114.29%
Marco Stornelli154.90%114.29%
Al Viro30.98%114.29%
Total306100.00%7100.00%


unsigned long sysv_count_free_blocks(struct super_block * sb) { struct sysv_sb_info * sbi = SYSV_SB(sb); int sb_count; int count; struct buffer_head * bh = NULL; sysv_zone_t *blocks; unsigned block; int n; /* * This code does not work at all for AFS (it has a bitmap * free list). As AFS is supposed to be read-only we just * lie and say it has no free block at all. */ if (sbi->s_type == FSTYPE_AFS) return 0; mutex_lock(&sbi->s_lock); sb_count = fs32_to_cpu(sbi, *sbi->s_free_blocks); if (0) goto trust_sb; /* this causes a lot of disk traffic ... */ count = 0; n = fs16_to_cpu(sbi, *sbi->s_bcache_count); blocks = sbi->s_bcache; while (1) { sysv_zone_t zone; if (n > sbi->s_flc_size) goto E2big; zone = 0; while (n && (zone = blocks[--n]) != 0) count++; if (zone == 0) break; block = fs32_to_cpu(sbi, zone); if (bh) brelse(bh); if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) goto Einval; block += sbi->s_block_base; bh = sb_bread(sb, block); if (!bh) goto Eio; n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data); blocks = get_chunk(sb, bh); } if (bh) brelse(bh); if (count != sb_count) goto Ecount; done: mutex_unlock(&sbi->s_lock); return count; Einval: printk("sysv_count_free_blocks: new block %d is not in data zone\n", block); goto trust_sb; Eio: printk("sysv_count_free_blocks: cannot read free-list block\n"); goto trust_sb; E2big: printk("sysv_count_free_blocks: >flc_size entries in free-list block\n"); if (bh) brelse(bh); trust_sb: count = sb_count; goto done; Ecount: printk("sysv_count_free_blocks: free block count was %d, " "correcting to %d\n", sb_count, count); if (!(sb->s_flags & MS_RDONLY)) { *sbi->s_free_blocks = cpu_to_fs32(sbi, count); dirty_sb(sb); } goto done; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds16946.69%330.00%
Linus Torvalds (pre-git)14138.95%440.00%
Christoph Hellwig339.12%110.00%
Marco Stornelli102.76%110.00%
Al Viro92.49%110.00%
Total362100.00%10100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)46845.48%533.33%
Linus Torvalds37736.64%320.00%
Christoph Hellwig12011.66%426.67%
Marco Stornelli454.37%16.67%
Al Viro181.75%16.67%
Andrew Morton10.10%16.67%
Total1029100.00%15100.00%
Directory: fs/sysv
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.