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_ll_rw_block(int rw, struct ufs_buffer_head *ubh)
 117{
 118        if (!ubh)
 119                return;
 120
 121        ll_rw_block(rw, ubh->count, ubh->bh);
 122}
 123
 124void ubh_wait_on_buffer (struct ufs_buffer_head * ubh)
 125{
 126        unsigned i;
 127        if (!ubh)
 128                return;
 129        for ( i = 0; i < ubh->count; i++ )
 130                wait_on_buffer (ubh->bh[i]);
 131}
 132
 133void ubh_bforget (struct ufs_buffer_head * ubh)
 134{
 135        unsigned i;
 136        if (!ubh) 
 137                return;
 138        for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) 
 139                bforget (ubh->bh[i]);
 140}
 141 
 142int ubh_buffer_dirty (struct ufs_buffer_head * ubh)
 143{
 144        unsigned i;
 145        unsigned result = 0;
 146        if (!ubh)
 147                return 0;
 148        for ( i = 0; i < ubh->count; i++ )
 149                result |= buffer_dirty(ubh->bh[i]);
 150        return result;
 151}
 152
 153void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, 
 154        unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size)
 155{
 156        unsigned len, bhno;
 157        if (size > (ubh->count << uspi->s_fshift))
 158                size = ubh->count << uspi->s_fshift;
 159        bhno = 0;
 160        while (size) {
 161                len = min_t(unsigned int, size, uspi->s_fsize);
 162                memcpy (mem, ubh->bh[bhno]->b_data, len);
 163                mem += uspi->s_fsize;
 164                size -= len;
 165                bhno++;
 166        }
 167}
 168
 169void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, 
 170        struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size)
 171{
 172        unsigned len, bhno;
 173        if (size > (ubh->count << uspi->s_fshift))
 174                size = ubh->count << uspi->s_fshift;
 175        bhno = 0;
 176        while (size) {
 177                len = min_t(unsigned int, size, uspi->s_fsize);
 178                memcpy (ubh->bh[bhno]->b_data, mem, len);
 179                mem += uspi->s_fsize;
 180                size -= len;
 181                bhno++;
 182        }
 183}
 184
 185dev_t
 186ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
 187{
 188        __u32 fs32;
 189        dev_t dev;
 190
 191        if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
 192                fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[1]);
 193        else
 194                fs32 = fs32_to_cpu(sb, ufsi->i_u1.i_data[0]);
 195        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 196        case UFS_ST_SUNx86:
 197        case UFS_ST_SUN:
 198                if ((fs32 & 0xffff0000) == 0 ||
 199                    (fs32 & 0xffff0000) == 0xffff0000)
 200                        dev = old_decode_dev(fs32 & 0x7fff);
 201                else
 202                        dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
 203                break;
 204
 205        default:
 206                dev = old_decode_dev(fs32);
 207                break;
 208        }
 209        return dev;
 210}
 211
 212void
 213ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
 214{
 215        __u32 fs32;
 216
 217        switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 218        case UFS_ST_SUNx86:
 219        case UFS_ST_SUN:
 220                fs32 = sysv_encode_dev(dev);
 221                if ((fs32 & 0xffff8000) == 0) {
 222                        fs32 = old_encode_dev(dev);
 223                }
 224                break;
 225
 226        default:
 227                fs32 = old_encode_dev(dev);
 228                break;
 229        }
 230        if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
 231                ufsi->i_u1.i_data[1] = cpu_to_fs32(sb, fs32);
 232        else
 233                ufsi->i_u1.i_data[0] = cpu_to_fs32(sb, fs32);
 234}
 235
 236/**
 237 * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist
 238 * read it from disk.
 239 * @mapping: the address_space to search
 240 * @index: the page index
 241 *
 242 * Locates the desired pagecache page, if not exist we'll read it,
 243 * locks it, increments its reference
 244 * count and returns its address.
 245 *
 246 */
 247
 248struct page *ufs_get_locked_page(struct address_space *mapping,
 249                                 pgoff_t index)
 250{
 251        struct page *page;
 252
 253        page = find_lock_page(mapping, index);
 254        if (!page) {
 255                page = read_mapping_page(mapping, index, NULL);
 256
 257                if (IS_ERR(page)) {
 258                        printk(KERN_ERR "ufs_change_blocknr: "
 259                               "read_mapping_page error: ino %lu, index: %lu\n",
 260                               mapping->host->i_ino, index);
 261                        goto out;
 262                }
 263
 264                lock_page(page);
 265
 266                if (unlikely(page->mapping == NULL)) {
 267                        /* Truncate got there first */
 268                        unlock_page(page);
 269                        page_cache_release(page);
 270                        page = NULL;
 271                        goto out;
 272                }
 273
 274                if (!PageUptodate(page) || PageError(page)) {
 275                        unlock_page(page);
 276                        page_cache_release(page);
 277
 278                        printk(KERN_ERR "ufs_change_blocknr: "
 279                               "can not read page: ino %lu, index: %lu\n",
 280                               mapping->host->i_ino, index);
 281
 282                        page = ERR_PTR(-EIO);
 283                }
 284        }
 285out:
 286        return page;
 287}
 288