brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 2acf191 Raw
270 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  linux/fs/ufs/util.c4 *5 * Copyright (C) 19986 * Daniel Pirkl <daniel.pirkl@email.cz>7 * Charles University, Faculty of Mathematics and Physics8 */9 10#include <linux/string.h>11#include <linux/slab.h>12#include <linux/buffer_head.h>13 14#include "ufs_fs.h"15#include "ufs.h"16#include "swab.h"17#include "util.h"18 19struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,20	struct super_block *sb, u64 fragment, u64 size)21{22	struct ufs_buffer_head * ubh;23	unsigned i, j ;24	u64  count = 0;25	if (size & ~uspi->s_fmask)26		return NULL;27	count = size >> uspi->s_fshift;28	if (count > UFS_MAXFRAG)29		return NULL;30	ubh = kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);31	if (!ubh)32		return NULL;33	ubh->fragment = fragment;34	ubh->count = count;35	for (i = 0; i < count; i++)36		if (!(ubh->bh[i] = sb_bread(sb, fragment + i)))37			goto failed;38	for (; i < UFS_MAXFRAG; i++)39		ubh->bh[i] = NULL;40	return ubh;41failed:42	for (j = 0; j < i; j++)43		brelse (ubh->bh[j]);44	kfree(ubh);45	return NULL;46}47 48struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,49	struct super_block *sb, u64 fragment, u64 size)50{51	unsigned i, j;52	u64 count = 0;53	if (size & ~uspi->s_fmask)54		return NULL;55	count = size >> uspi->s_fshift;56	if (count <= 0 || count > UFS_MAXFRAG)57		return NULL;58	USPI_UBH(uspi)->fragment = fragment;59	USPI_UBH(uspi)->count = count;60	for (i = 0; i < count; i++)61		if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i)))62			goto failed;63	for (; i < UFS_MAXFRAG; i++)64		USPI_UBH(uspi)->bh[i] = NULL;65	return USPI_UBH(uspi);66failed:67	for (j = 0; j < i; j++)68		brelse (USPI_UBH(uspi)->bh[j]);69	return NULL;70}71 72void ubh_brelse (struct ufs_buffer_head * ubh)73{74	unsigned i;75	if (!ubh)76		return;77	for (i = 0; i < ubh->count; i++)78		brelse (ubh->bh[i]);79	kfree (ubh);80}81 82void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)83{84	unsigned i;85	if (!USPI_UBH(uspi))86		return;87	for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) {88		brelse (USPI_UBH(uspi)->bh[i]);89		USPI_UBH(uspi)->bh[i] = NULL;90	}91}92 93void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh)94{95	unsigned i;96	if (!ubh)97		return;98	for ( i = 0; i < ubh->count; i++ )99		mark_buffer_dirty (ubh->bh[i]);100}101 102void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag)103{104	unsigned i;105	if (!ubh)106		return;107	if (flag) {108		for ( i = 0; i < ubh->count; i++ )109			set_buffer_uptodate (ubh->bh[i]);110	} else {111		for ( i = 0; i < ubh->count; i++ )112			clear_buffer_uptodate (ubh->bh[i]);113	}114}115 116void ubh_sync_block(struct ufs_buffer_head *ubh)117{118	if (ubh) {119		unsigned i;120 121		for (i = 0; i < ubh->count; i++)122			write_dirty_buffer(ubh->bh[i], 0);123 124		for (i = 0; i < ubh->count; i++)125			wait_on_buffer(ubh->bh[i]);126	}127}128 129void ubh_bforget (struct ufs_buffer_head * ubh)130{131	unsigned i;132	if (!ubh) 133		return;134	for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) 135		bforget (ubh->bh[i]);136}137 138int ubh_buffer_dirty (struct ufs_buffer_head * ubh)139{140	unsigned i;141	unsigned result = 0;142	if (!ubh)143		return 0;144	for ( i = 0; i < ubh->count; i++ )145		result |= buffer_dirty(ubh->bh[i]);146	return result;147}148 149void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, 150	unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size)151{152	unsigned len, bhno;153	if (size > (ubh->count << uspi->s_fshift))154		size = ubh->count << uspi->s_fshift;155	bhno = 0;156	while (size) {157		len = min_t(unsigned int, size, uspi->s_fsize);158		memcpy (mem, ubh->bh[bhno]->b_data, len);159		mem += uspi->s_fsize;160		size -= len;161		bhno++;162	}163}164 165void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, 166	struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size)167{168	unsigned len, bhno;169	if (size > (ubh->count << uspi->s_fshift))170		size = ubh->count << uspi->s_fshift;171	bhno = 0;172	while (size) {173		len = min_t(unsigned int, size, uspi->s_fsize);174		memcpy (ubh->bh[bhno]->b_data, mem, len);175		mem += uspi->s_fsize;176		size -= len;177		bhno++;178	}179}180 181dev_t182ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)183{184	__u32 fs32;185	dev_t dev;186 187	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)188		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]);189	else190		fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]);191	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {192	case UFS_ST_SUNx86:193	case UFS_ST_SUN:194		if ((fs32 & 0xffff0000) == 0 ||195		    (fs32 & 0xffff0000) == 0xffff0000)196			dev = old_decode_dev(fs32 & 0x7fff);197		else198			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));199		break;200 201	default:202		dev = old_decode_dev(fs32);203		break;204	}205	return dev;206}207 208void209ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)210{211	__u32 fs32;212 213	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {214	case UFS_ST_SUNx86:215	case UFS_ST_SUN:216		fs32 = sysv_encode_dev(dev);217		if ((fs32 & 0xffff8000) == 0) {218			fs32 = old_encode_dev(dev);219		}220		break;221 222	default:223		fs32 = old_encode_dev(dev);224		break;225	}226	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)227		ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32);228	else229		ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);230}231 232/**233 * ufs_get_locked_folio() - locate, pin and lock a pagecache folio, if not exist234 * read it from disk.235 * @mapping: the address_space to search236 * @index: the page index237 *238 * Locates the desired pagecache folio, if not exist we'll read it,239 * locks it, increments its reference240 * count and returns its address.241 *242 */243struct folio *ufs_get_locked_folio(struct address_space *mapping,244				 pgoff_t index)245{246	struct inode *inode = mapping->host;247	struct folio *folio = filemap_lock_folio(mapping, index);248	if (IS_ERR(folio)) {249		folio = read_mapping_folio(mapping, index, NULL);250 251		if (IS_ERR(folio)) {252			printk(KERN_ERR "ufs_change_blocknr: read_mapping_folio error: ino %lu, index: %lu\n",253			       mapping->host->i_ino, index);254			return folio;255		}256 257		folio_lock(folio);258 259		if (unlikely(folio->mapping == NULL)) {260			/* Truncate got there first */261			folio_unlock(folio);262			folio_put(folio);263			return NULL;264		}265	}266	if (!folio_buffers(folio))267		create_empty_buffers(folio, 1 << inode->i_blkbits, 0);268	return folio;269}270