linux/fs/ufs/util.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/ufs/util.c
   3 *
   4 * Copyright (C) 1998
   5 * Daniel Pirkl <daniel.pirkl@email.cz>
   6 * Charles University, Faculty of Mathematics and Physics
   7 */
   8 
   9#include <linux/string.h>
  10#include <linux/slab.h>
  11#include <linux/buffer_head.h>
  12
  13#include "ufs_fs.h"
  14#include "ufs.h"
  15#include "swab.h"
  16#include "util.h"
  17
  18struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
  19        struct super_block *sb, u64 fragment, u64 size)
  20{
  21        struct ufs_buffer_head * ubh;
  22        unsigned i, j ;
  23        u64  count = 0;
  24        if (size & ~uspi->s_fmask)
  25                return NULL;
  26        count = size >> uspi->s_fshift;
  27        if (count > UFS_MAXFRAG)
  28                return NULL;
  29        ubh = (struct ufs_buffer_head *)
  30                kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL);
  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], WRITE);
 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_t
 182ufs_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        else
 190                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                else
 198                        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
 208void
 209ufs_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        else
 229                ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
 230}
 231
 232/**
 233 * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
 234 * read it from disk.
 235 * @mapping: the address_space to search
 236 * @index: the page index
 237 *
 238 * Locates the desired pagecache page, if not exist we'll read it,
 239 * locks it, increments its reference
 240 * count and returns its address.
 241 *
 242 */
 243
 244struct page *ufs_get_locked_page(struct address_space *mapping,
 245                                 pgoff_t index)
 246{
 247        struct page *page;
 248
 249        page = find_lock_page(mapping, index);
 250        if (!page) {
 251                page = read_mapping_page(mapping, index, NULL);
 252
 253                if (IS_ERR(page)) {
 254                        printk(KERN_ERR "ufs_change_blocknr: "
 255                               "read_mapping_page error: ino %lu, index: %lu\n",
 256                               mapping->host->i_ino, index);
 257                        goto out;
 258                }
 259
 260                lock_page(page);
 261
 262                if (unlikely(page->mapping == NULL)) {
 263                        /* Truncate got there first */
 264                        unlock_page(page);
 265                        page_cache_release(page);
 266                        page = NULL;
 267                        goto out;
 268                }
 269
 270                if (!PageUptodate(page) || PageError(page)) {
 271                        unlock_page(page);
 272                        page_cache_release(page);
 273
 274                        printk(KERN_ERR "ufs_change_blocknr: "
 275                               "can not read page: ino %lu, index: %lu\n",
 276                               mapping->host->i_ino, index);
 277
 278                        page = ERR_PTR(-EIO);
 279                }
 280        }
 281out:
 282        return page;
 283}
 284