The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ufs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/fs/ufs/inode.c
    3  *
    4  * Copyright (C) 1998
    5  * Daniel Pirkl <daniel.pirkl@email.cz>
    6  * Charles University, Faculty of Mathematics and Physics
    7  *
    8  *  from
    9  *
   10  *  linux/fs/ext2/inode.c
   11  *
   12  * Copyright (C) 1992, 1993, 1994, 1995
   13  * Remy Card (card@masi.ibp.fr)
   14  * Laboratoire MASI - Institut Blaise Pascal
   15  * Universite Pierre et Marie Curie (Paris VI)
   16  *
   17  *  from
   18  *
   19  *  linux/fs/minix/inode.c
   20  *
   21  *  Copyright (C) 1991, 1992  Linus Torvalds
   22  *
   23  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
   24  *  Big-endian to little-endian byte-swapping/bitmaps by
   25  *        David S. Miller (davem@caip.rutgers.edu), 1995
   26  */
   27 
   28 #include <asm/uaccess.h>
   29 #include <asm/system.h>
   30 
   31 #include <linux/errno.h>
   32 #include <linux/fs.h>
   33 #include <linux/ufs_fs.h>
   34 #include <linux/sched.h>
   35 #include <linux/stat.h>
   36 #include <linux/string.h>
   37 #include <linux/locks.h>
   38 #include <linux/mm.h>
   39 #include <linux/smp_lock.h>
   40 
   41 #include "swab.h"
   42 #include "util.h"
   43 
   44 #undef UFS_INODE_DEBUG
   45 #undef UFS_INODE_DEBUG_MORE
   46 
   47 #ifdef UFS_INODE_DEBUG
   48 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
   49 #else
   50 #define UFSD(x)
   51 #endif
   52 
   53 static int ufs_block_to_path(struct inode *inode, long i_block, int offsets[4])
   54 {
   55         struct ufs_sb_private_info *uspi = inode->i_sb->u.ufs_sb.s_uspi;
   56         int ptrs = uspi->s_apb;
   57         int ptrs_bits = uspi->s_apbshift;
   58         const long direct_blocks = UFS_NDADDR,
   59                 indirect_blocks = ptrs,
   60                 double_blocks = (1 << (ptrs_bits * 2));
   61         int n = 0;
   62 
   63         if (i_block < 0) {
   64                 ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0");
   65         } else if (i_block < direct_blocks) {
   66                 offsets[n++] = i_block;
   67         } else if ((i_block -= direct_blocks) < indirect_blocks) {
   68                 offsets[n++] = UFS_IND_BLOCK;
   69                 offsets[n++] = i_block;
   70         } else if ((i_block -= indirect_blocks) < double_blocks) {
   71                 offsets[n++] = UFS_DIND_BLOCK;
   72                 offsets[n++] = i_block >> ptrs_bits;
   73                 offsets[n++] = i_block & (ptrs - 1);
   74         } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
   75                 offsets[n++] = UFS_TIND_BLOCK;
   76                 offsets[n++] = i_block >> (ptrs_bits * 2);
   77                 offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1);
   78                 offsets[n++] = i_block & (ptrs - 1);
   79         } else {
   80                 ufs_warning(inode->i_sb, "ufs_block_to_path", "block > big");
   81         }
   82         return n;
   83 }
   84 
   85 int ufs_frag_map(struct inode *inode, int frag)
   86 {
   87         struct super_block *sb = inode->i_sb;
   88         struct ufs_sb_private_info *uspi = sb->u.ufs_sb.s_uspi;
   89         int mask = uspi->s_apbmask>>uspi->s_fpbshift;
   90         int shift = uspi->s_apbshift-uspi->s_fpbshift;
   91         int offsets[4], *p;
   92         int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
   93         int ret = 0;
   94         u32 block;
   95 
   96         if (depth == 0)
   97                 return 0;
   98 
   99         p = offsets;
  100 
  101         lock_kernel();
  102         block = inode->u.ufs_i.i_u1.i_data[*p++];
  103         if (!block)
  104                 goto out;
  105         while (--depth) {
  106                 struct buffer_head *bh;
  107                 int n = *p++;
  108 
  109                 bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
  110                 if (!bh)
  111                         goto out;
  112                 block = ((u32*) bh->b_data)[n & mask];
  113                 brelse (bh);
  114                 if (!block)
  115                         goto out;
  116         }
  117         ret = uspi->s_sbbase + fs32_to_cpu(sb, block) + (frag & uspi->s_fpbmask);
  118 out:
  119         unlock_kernel();
  120         return ret;
  121 }
  122 
  123 static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
  124         unsigned int fragment, unsigned int new_fragment,
  125         unsigned int required, int *err, int metadata, long *phys, int *new)
  126 {
  127         struct super_block * sb;
  128         struct ufs_sb_private_info * uspi;
  129         struct buffer_head * result;
  130         unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
  131         unsigned tmp, goal;
  132         u32 * p, * p2;
  133 
  134         UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
  135                 inode->i_ino, fragment, new_fragment, required))         
  136 
  137         sb = inode->i_sb;
  138         uspi = sb->u.ufs_sb.s_uspi;
  139         block = ufs_fragstoblks (fragment);
  140         blockoff = ufs_fragnum (fragment);
  141         p = inode->u.ufs_i.i_u1.i_data + block;
  142         goal = 0;
  143 
  144 repeat:
  145         tmp = fs32_to_cpu(sb, *p);
  146         lastfrag = inode->u.ufs_i.i_lastfrag;
  147         if (tmp && fragment < lastfrag) {
  148                 if (metadata) {
  149                         result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
  150                         if (tmp == fs32_to_cpu(sb, *p)) {
  151                                 UFSD(("EXIT, result %u\n", tmp + blockoff))
  152                                 return result;
  153                         }
  154                         brelse (result);
  155                         goto repeat;
  156                 } else {
  157                         *phys = tmp;
  158                         return NULL;
  159                 }
  160         }
  161 
  162         lastblock = ufs_fragstoblks (lastfrag);
  163         lastblockoff = ufs_fragnum (lastfrag);
  164         /*
  165          * We will extend file into new block beyond last allocated block
  166          */
  167         if (lastblock < block) {
  168                 /*
  169                  * We must reallocate last allocated block
  170                  */
  171                 if (lastblockoff) {
  172                         p2 = inode->u.ufs_i.i_u1.i_data + lastblock;
  173                         tmp = ufs_new_fragments (inode, p2, lastfrag, 
  174                                 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, err);
  175                         if (!tmp) {
  176                                 if (lastfrag != inode->u.ufs_i.i_lastfrag)
  177                                         goto repeat;
  178                                 else
  179                                         return NULL;
  180                         }
  181                         lastfrag = inode->u.ufs_i.i_lastfrag;
  182                         
  183                 }
  184                 goal = fs32_to_cpu(sb, inode->u.ufs_i.i_u1.i_data[lastblock]) + uspi->s_fpb;
  185                 tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
  186                         goal, required + blockoff, err);
  187         }
  188         /*
  189          * We will extend last allocated block
  190          */
  191         else if (lastblock == block) {
  192                 tmp = ufs_new_fragments (inode, p, fragment - (blockoff - lastblockoff),
  193                         fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff), err);
  194         }
  195         /*
  196          * We will allocate new block before last allocated block
  197          */
  198         else /* (lastblock > block) */ {
  199                 if (lastblock && (tmp = fs32_to_cpu(sb, inode->u.ufs_i.i_u1.i_data[lastblock-1])))
  200                         goal = tmp + uspi->s_fpb;
  201                 tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
  202                         goal, uspi->s_fpb, err);
  203         }
  204         if (!tmp) {
  205                 if ((!blockoff && *p) || 
  206                     (blockoff && lastfrag != inode->u.ufs_i.i_lastfrag))
  207                         goto repeat;
  208                 *err = -ENOSPC;
  209                 return NULL;
  210         }
  211 
  212         /* The nullification of framgents done in ufs/balloc.c is
  213          * something I don't have the stomache to move into here right
  214          * now. -DaveM
  215          */
  216         if (metadata) {
  217                 result = sb_getblk(inode->i_sb, tmp + blockoff);
  218         } else {
  219                 *phys = tmp;
  220                 result = NULL;
  221                 *err = 0;
  222                 *new = 1;
  223         }
  224 
  225         inode->i_ctime = CURRENT_TIME;
  226         if (IS_SYNC(inode))
  227                 ufs_sync_inode (inode);
  228         mark_inode_dirty(inode);
  229         UFSD(("EXIT, result %u\n", tmp + blockoff))
  230         return result;
  231 }
  232 
  233 static struct buffer_head * ufs_block_getfrag (struct inode *inode,
  234         struct buffer_head *bh, unsigned int fragment, unsigned int new_fragment, 
  235         unsigned int blocksize, int * err, int metadata, long *phys, int *new)
  236 {
  237         struct super_block * sb;
  238         struct ufs_sb_private_info * uspi;
  239         struct buffer_head * result;
  240         unsigned tmp, goal, block, blockoff;
  241         u32 * p;
  242 
  243         sb = inode->i_sb;
  244         uspi = sb->u.ufs_sb.s_uspi;
  245         block = ufs_fragstoblks (fragment);
  246         blockoff = ufs_fragnum (fragment);
  247 
  248         UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment))  
  249 
  250         result = NULL;
  251         if (!bh)
  252                 goto out;
  253         if (!buffer_uptodate(bh)) {
  254                 ll_rw_block (READ, 1, &bh);
  255                 wait_on_buffer (bh);
  256                 if (!buffer_uptodate(bh))
  257                         goto out;
  258         }
  259 
  260         p = (u32 *) bh->b_data + block;
  261 repeat:
  262         tmp = fs32_to_cpu(sb, *p);
  263         if (tmp) {
  264                 if (metadata) {
  265                         result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
  266                         if (tmp == fs32_to_cpu(sb, *p))
  267                                 goto out;
  268                         brelse (result);
  269                         goto repeat;
  270                 } else {
  271                         *phys = tmp;
  272                         goto out;
  273                 }
  274         }
  275 
  276         if (block && (tmp = fs32_to_cpu(sb, ((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
  277                 goal = tmp + uspi->s_fpb;
  278         else
  279                 goal = bh->b_blocknr + uspi->s_fpb;
  280         tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err);
  281         if (!tmp) {
  282                 if (fs32_to_cpu(sb, *p))
  283                         goto repeat;
  284                 goto out;
  285         }               
  286 
  287         /* The nullification of framgents done in ufs/balloc.c is
  288          * something I don't have the stomache to move into here right
  289          * now. -DaveM
  290          */
  291         if (metadata) {
  292                 result = sb_getblk(sb, tmp + blockoff);
  293         } else {
  294                 *phys = tmp;
  295                 *new = 1;
  296         }
  297 
  298         mark_buffer_dirty(bh);
  299         if (IS_SYNC(inode)) {
  300                 ll_rw_block (WRITE, 1, &bh);
  301                 wait_on_buffer (bh);
  302         }
  303         inode->i_ctime = CURRENT_TIME;
  304         mark_inode_dirty(inode);
  305 out:
  306         brelse (bh);
  307         UFSD(("EXIT, result %u\n", tmp + blockoff))
  308         return result;
  309 }
  310 
  311 static int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
  312 {
  313         struct super_block * sb;
  314         struct ufs_sb_private_info * uspi;
  315         struct buffer_head * bh;
  316         int ret, err, new;
  317         unsigned long ptr, phys;
  318         
  319         sb = inode->i_sb;
  320         uspi = sb->u.ufs_sb.s_uspi;
  321 
  322         if (!create) {
  323                 phys = ufs_frag_map(inode, fragment);
  324                 if (phys) {
  325                         bh_result->b_dev = inode->i_dev;
  326                         bh_result->b_blocknr = phys;
  327                         bh_result->b_state |= (1UL << BH_Mapped);
  328                 }
  329                 return 0;
  330         }
  331 
  332         err = -EIO;
  333         new = 0;
  334         ret = 0;
  335         bh = NULL;
  336 
  337         lock_kernel();
  338 
  339         UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
  340         if (fragment < 0)
  341                 goto abort_negative;
  342         if (fragment >
  343             ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb)
  344              << uspi->s_fpbshift))
  345                 goto abort_too_big;
  346 
  347         err = 0;
  348         ptr = fragment;
  349           
  350         /*
  351          * ok, these macros clean the logic up a bit and make
  352          * it much more readable:
  353          */
  354 #define GET_INODE_DATABLOCK(x) \
  355                 ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new)
  356 #define GET_INODE_PTR(x) \
  357                 ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL)
  358 #define GET_INDIRECT_DATABLOCK(x) \
  359                 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
  360                                   &err, 0, &phys, &new);
  361 #define GET_INDIRECT_PTR(x) \
  362                 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
  363                                   &err, 1, NULL, NULL);
  364 
  365         if (ptr < UFS_NDIR_FRAGMENT) {
  366                 bh = GET_INODE_DATABLOCK(ptr);
  367                 goto out;
  368         }
  369         ptr -= UFS_NDIR_FRAGMENT;
  370         if (ptr < (1 << (uspi->s_apbshift + uspi->s_fpbshift))) {
  371                 bh = GET_INODE_PTR(UFS_IND_FRAGMENT + (ptr >> uspi->s_apbshift));
  372                 goto get_indirect;
  373         }
  374         ptr -= 1 << (uspi->s_apbshift + uspi->s_fpbshift);
  375         if (ptr < (1 << (uspi->s_2apbshift + uspi->s_fpbshift))) {
  376                 bh = GET_INODE_PTR(UFS_DIND_FRAGMENT + (ptr >> uspi->s_2apbshift));
  377                 goto get_double;
  378         }
  379         ptr -= 1 << (uspi->s_2apbshift + uspi->s_fpbshift);
  380         bh = GET_INODE_PTR(UFS_TIND_FRAGMENT + (ptr >> uspi->s_3apbshift));
  381         bh = GET_INDIRECT_PTR((ptr >> uspi->s_2apbshift) & uspi->s_apbmask);
  382 get_double:
  383         bh = GET_INDIRECT_PTR((ptr >> uspi->s_apbshift) & uspi->s_apbmask);
  384 get_indirect:
  385         bh = GET_INDIRECT_DATABLOCK(ptr & uspi->s_apbmask);
  386 
  387 #undef GET_INODE_DATABLOCK
  388 #undef GET_INODE_PTR
  389 #undef GET_INDIRECT_DATABLOCK
  390 #undef GET_INDIRECT_PTR
  391 
  392 out:
  393         if (err)
  394                 goto abort;
  395         bh_result->b_dev = inode->i_dev;
  396         bh_result->b_blocknr = phys;
  397         bh_result->b_state |= (1UL << BH_Mapped);
  398         if (new)
  399                 bh_result->b_state |= (1UL << BH_New);
  400 abort:
  401         unlock_kernel();
  402         return err;
  403 
  404 abort_negative:
  405         ufs_warning(sb, "ufs_get_block", "block < 0");
  406         goto abort;
  407 
  408 abort_too_big:
  409         ufs_warning(sb, "ufs_get_block", "block > big");
  410         goto abort;
  411 }
  412 
  413 struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment,
  414                                 int create, int *err)
  415 {
  416         struct buffer_head dummy;
  417         int error;
  418 
  419         dummy.b_state = 0;
  420         dummy.b_blocknr = -1000;
  421         error = ufs_getfrag_block(inode, fragment, &dummy, create);
  422         *err = error;
  423         if (!error && buffer_mapped(&dummy)) {
  424                 struct buffer_head *bh;
  425                 bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
  426                 if (buffer_new(&dummy)) {
  427                         memset(bh->b_data, 0, inode->i_sb->s_blocksize);
  428                         mark_buffer_uptodate(bh, 1);
  429                         mark_buffer_dirty(bh);
  430                 }
  431                 return bh;
  432         }
  433         return NULL;
  434 }
  435 
  436 struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
  437         int create, int * err)
  438 {
  439         struct buffer_head * bh;
  440 
  441         UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
  442         bh = ufs_getfrag (inode, fragment, create, err);
  443         if (!bh || buffer_uptodate(bh))                 
  444                 return bh;
  445         ll_rw_block (READ, 1, &bh);
  446         wait_on_buffer (bh);
  447         if (buffer_uptodate(bh))
  448                 return bh;
  449         brelse (bh);
  450         *err = -EIO;
  451         return NULL;
  452 }
  453 
  454 static int ufs_writepage(struct page *page)
  455 {
  456         return block_write_full_page(page,ufs_getfrag_block);
  457 }
  458 static int ufs_readpage(struct file *file, struct page *page)
  459 {
  460         return block_read_full_page(page,ufs_getfrag_block);
  461 }
  462 static int ufs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  463 {
  464         return block_prepare_write(page,from,to,ufs_getfrag_block);
  465 }
  466 static int ufs_bmap(struct address_space *mapping, long block)
  467 {
  468         return generic_block_bmap(mapping,block,ufs_getfrag_block);
  469 }
  470 struct address_space_operations ufs_aops = {
  471         readpage: ufs_readpage,
  472         writepage: ufs_writepage,
  473         sync_page: block_sync_page,
  474         prepare_write: ufs_prepare_write,
  475         commit_write: generic_commit_write,
  476         bmap: ufs_bmap
  477 };
  478 
  479 void ufs_read_inode (struct inode * inode)
  480 {
  481         struct super_block * sb;
  482         struct ufs_sb_private_info * uspi;
  483         struct ufs_inode * ufs_inode;   
  484         struct buffer_head * bh;
  485         unsigned i;
  486         unsigned flags;
  487         
  488         UFSD(("ENTER, ino %lu\n", inode->i_ino))
  489         
  490         sb = inode->i_sb;
  491         uspi = sb->u.ufs_sb.s_uspi;
  492         flags = sb->u.ufs_sb.s_flags;
  493 
  494         if (inode->i_ino < UFS_ROOTINO || 
  495             inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
  496                 ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
  497                 goto bad_inode;
  498         }
  499         
  500         bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
  501         if (!bh) {
  502                 ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
  503                 goto bad_inode;
  504         }
  505         ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
  506 
  507         /*
  508          * Copy data to the in-core inode.
  509          */
  510         inode->i_mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
  511         inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
  512         if (inode->i_nlink == 0)
  513                 ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
  514         
  515         /*
  516          * Linux now has 32-bit uid and gid, so we can support EFT.
  517          */
  518         inode->i_uid = ufs_get_inode_uid(sb, ufs_inode);
  519         inode->i_gid = ufs_get_inode_gid(sb, ufs_inode);
  520 
  521         inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
  522         inode->i_atime = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
  523         inode->i_ctime = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
  524         inode->i_mtime = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
  525         inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
  526         inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat) */
  527         inode->i_version = ++event;
  528 
  529         inode->u.ufs_i.i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
  530         inode->u.ufs_i.i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
  531         inode->u.ufs_i.i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
  532         inode->u.ufs_i.i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
  533         inode->u.ufs_i.i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
  534         
  535         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
  536                 ;
  537         else if (inode->i_blocks) {
  538                 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
  539                         inode->u.ufs_i.i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i];
  540         }
  541         else {
  542                 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
  543                         inode->u.ufs_i.i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
  544         }
  545 
  546 
  547         if (S_ISREG(inode->i_mode)) {
  548                 inode->i_op = &ufs_file_inode_operations;
  549                 inode->i_fop = &ufs_file_operations;
  550                 inode->i_mapping->a_ops = &ufs_aops;
  551         } else if (S_ISDIR(inode->i_mode)) {
  552                 inode->i_op = &ufs_dir_inode_operations;
  553                 inode->i_fop = &ufs_dir_operations;
  554         } else if (S_ISLNK(inode->i_mode)) {
  555                 if (!inode->i_blocks)
  556                         inode->i_op = &ufs_fast_symlink_inode_operations;
  557                 else {
  558                         inode->i_op = &page_symlink_inode_operations;
  559                         inode->i_mapping->a_ops = &ufs_aops;
  560                 }
  561         } else
  562                 init_special_inode(inode, inode->i_mode,
  563                         fs32_to_cpu(sb, ufs_inode->ui_u2.ui_addr.ui_db[0]));
  564 
  565         brelse (bh);
  566 
  567         UFSD(("EXIT\n"))
  568         return;
  569 
  570 bad_inode:
  571         make_bad_inode(inode);
  572         return;
  573 }
  574 
  575 static int ufs_update_inode(struct inode * inode, int do_sync)
  576 {
  577         struct super_block * sb;
  578         struct ufs_sb_private_info * uspi;
  579         struct buffer_head * bh;
  580         struct ufs_inode * ufs_inode;
  581         unsigned i;
  582         unsigned flags;
  583 
  584         UFSD(("ENTER, ino %lu\n", inode->i_ino))
  585 
  586         sb = inode->i_sb;
  587         uspi = sb->u.ufs_sb.s_uspi;
  588         flags = sb->u.ufs_sb.s_flags;
  589 
  590         if (inode->i_ino < UFS_ROOTINO || 
  591             inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
  592                 ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
  593                 return -1;
  594         }
  595 
  596         bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
  597         if (!bh) {
  598                 ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
  599                 return -1;
  600         }
  601         ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode));
  602 
  603         ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
  604         ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
  605 
  606         ufs_set_inode_uid(sb, ufs_inode, inode->i_uid);
  607         ufs_set_inode_gid(sb, ufs_inode, inode->i_gid);
  608                 
  609         ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
  610         ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime);
  611         ufs_inode->ui_atime.tv_usec = 0;
  612         ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime);
  613         ufs_inode->ui_ctime.tv_usec = 0;
  614         ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime);
  615         ufs_inode->ui_mtime.tv_usec = 0;
  616         ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
  617         ufs_inode->ui_flags = cpu_to_fs32(sb, inode->u.ufs_i.i_flags);
  618         ufs_inode->ui_gen = cpu_to_fs32(sb, inode->u.ufs_i.i_gen);
  619 
  620         if ((flags & UFS_UID_MASK) == UFS_UID_EFT) {
  621                 ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, inode->u.ufs_i.i_shadow);
  622                 ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, inode->u.ufs_i.i_oeftflag);
  623         }
  624 
  625         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
  626                 ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev));
  627         else if (inode->i_blocks) {
  628                 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
  629                         ufs_inode->ui_u2.ui_addr.ui_db[i] = inode->u.ufs_i.i_u1.i_data[i];
  630         }
  631         else {
  632                 for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
  633                         ufs_inode->ui_u2.ui_symlink[i] = inode->u.ufs_i.i_u1.i_symlink[i];
  634         }
  635 
  636         if (!inode->i_nlink)
  637                 memset (ufs_inode, 0, sizeof(struct ufs_inode));
  638                 
  639         mark_buffer_dirty(bh);
  640         if (do_sync) {
  641                 ll_rw_block (WRITE, 1, &bh);
  642                 wait_on_buffer (bh);
  643         }
  644         brelse (bh);
  645         
  646         UFSD(("EXIT\n"))
  647         return 0;
  648 }
  649 
  650 void ufs_write_inode (struct inode * inode, int wait)
  651 {
  652         lock_kernel();
  653         ufs_update_inode (inode, wait);
  654         unlock_kernel();
  655 }
  656 
  657 int ufs_sync_inode (struct inode *inode)
  658 {
  659         return ufs_update_inode (inode, 1);
  660 }
  661 
  662 void ufs_delete_inode (struct inode * inode)
  663 {
  664         /*inode->u.ufs_i.i_dtime = CURRENT_TIME;*/
  665         lock_kernel();
  666         mark_inode_dirty(inode);
  667         ufs_update_inode(inode, IS_SYNC(inode));
  668         inode->i_size = 0;
  669         if (inode->i_blocks)
  670                 ufs_truncate (inode);
  671         ufs_free_inode (inode);
  672         unlock_kernel();
  673 }

Cache object: 4f4953dfd888625881595df4736a6b88


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.