]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/xfs/xfs_iomap.c
Merge with ../linux-2.6
[linux-2.6-omap-h63xx.git] / fs / xfs / xfs_iomap.c
index 469e1a7939d44fbbe4dfbdbe8c9b2e90f0d4f7f2..45a77a3a6c07ed60b2a4fe041c6496c5ded3e1a5 100644 (file)
@@ -1,40 +1,25 @@
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.         Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
 #include "xfs.h"
-
 #include "xfs_fs.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
 #include "xfs_log.h"
+#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_dmapi.h"
 #include "xfs_quota.h"
 #include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_attr_sf.h"
 #include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
+#include "xfs_ialloc.h"
+#include "xfs_btree.h"
 #include "xfs_bmap.h"
 #include "xfs_bit.h"
 #include "xfs_rtalloc.h"
@@ -226,13 +211,12 @@ xfs_iomap(
                xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
                lockmode = XFS_LCK_MAP_SHARED(mp, io);
                bmapi_flags = XFS_BMAPI_ENTIRE;
-               if (flags & BMAPI_IGNSTATE)
-                       bmapi_flags |= XFS_BMAPI_IGSTATE;
                break;
        case BMAPI_WRITE:
                xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
                lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
-               bmapi_flags = 0;
+               if (flags & BMAPI_IGNSTATE)
+                       bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
                XFS_ILOCK(mp, io, lockmode);
                break;
        case BMAPI_ALLOCATE:
@@ -380,20 +364,18 @@ xfs_iomap_write_direct(
        xfs_fileoff_t   offset_fsb;
        xfs_fileoff_t   last_fsb;
        xfs_filblks_t   count_fsb;
-       xfs_fsize_t     isize;
        xfs_fsblock_t   firstfsb;
-       int             nimaps, maps;
+       int             nimaps;
        int             error;
        int             bmapi_flag;
+       int             quota_flag;
        int             rt;
        xfs_trans_t     *tp;
-       xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
+       xfs_bmbt_irec_t imap;
        xfs_bmap_free_t free_list;
-       int             aeof;
-       xfs_filblks_t   datablocks;
+       xfs_filblks_t   qblocks, resblks;
        int             committed;
-       int             numrtextents;
-       uint            resblks;
+       int             resrtextents;
 
        /*
         * Make sure that the dquots are there. This doesn't hold
@@ -403,15 +385,6 @@ xfs_iomap_write_direct(
        if (error)
                return XFS_ERROR(error);
 
-       maps = min(XFS_WRITE_IMAPS, *nmaps);
-       nimaps = maps;
-
-       isize = ip->i_d.di_size;
-       aeof = (offset + count) > isize;
-
-       if (io->io_new_size > isize)
-               isize = io->io_new_size;
-
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
        last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
        count_fsb = last_fsb - offset_fsb;
@@ -419,7 +392,6 @@ xfs_iomap_write_direct(
                xfs_fileoff_t   map_last_fsb;
 
                map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
-
                if (map_last_fsb < last_fsb) {
                        last_fsb = map_last_fsb;
                        count_fsb = last_fsb - offset_fsb;
@@ -428,56 +400,46 @@ xfs_iomap_write_direct(
        }
 
        /*
-        * determine if reserving space on
-        * the data or realtime partition.
+        * Determine if reserving space on the data or realtime partition.
         */
        if ((rt = XFS_IS_REALTIME_INODE(ip))) {
-               int     sbrtextsize, iprtextsize;
-
-               sbrtextsize = mp->m_sb.sb_rextsize;
-               iprtextsize =
-                       ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
-               numrtextents = (count_fsb + iprtextsize - 1);
-               do_div(numrtextents, sbrtextsize);
-               datablocks = 0;
+               xfs_extlen_t    extsz;
+
+               if (!(extsz = ip->i_d.di_extsize))
+                       extsz = mp->m_sb.sb_rextsize;
+               resrtextents = qblocks = (count_fsb + extsz - 1);
+               do_div(resrtextents, mp->m_sb.sb_rextsize);
+               resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+               quota_flag = XFS_QMOPT_RES_RTBLKS;
        } else {
-               datablocks = count_fsb;
-               numrtextents = 0;
+               resrtextents = 0;
+               resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb);
+               quota_flag = XFS_QMOPT_RES_REGBLKS;
        }
 
        /*
-        * allocate and setup the transaction
+        * Allocate and setup the transaction
         */
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-
-       resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-
        error = xfs_trans_reserve(tp, resblks,
-                       XFS_WRITE_LOG_RES(mp), numrtextents,
+                       XFS_WRITE_LOG_RES(mp), resrtextents,
                        XFS_TRANS_PERM_LOG_RES,
                        XFS_WRITE_LOG_COUNT);
 
        /*
-        * check for running out of space
+        * Check for running out of space, note: need lock to return
         */
        if (error)
-               /*
-                * Free the transaction structure.
-                */
                xfs_trans_cancel(tp, 0);
-
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-
        if (error)
-               goto error_out; /* Don't return in above if .. trans ..,
-                                       need lock to return */
+               goto error_out;
 
-       if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
+       if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
                error = (EDQUOT);
                goto error1;
        }
-       nimaps = 1;
 
        bmapi_flag = XFS_BMAPI_WRITE;
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -487,37 +449,34 @@ xfs_iomap_write_direct(
                bmapi_flag |= XFS_BMAPI_PREALLOC;
 
        /*
-        * issue the bmapi() call to allocate the blocks
+        * Issue the bmapi() call to allocate the blocks
         */
        XFS_BMAP_INIT(&free_list, &firstfsb);
-       imapp = &imap[0];
+       nimaps = 1;
        error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
-               bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
-       if (error) {
+               bmapi_flag, &firstfsb, 0, &imap, &nimaps, &free_list);
+       if (error)
                goto error0;
-       }
 
        /*
-        * complete the transaction
+        * Complete the transaction
         */
-
        error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
-       if (error) {
+       if (error)
                goto error0;
-       }
-
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-       if (error) {
+       if (error)
                goto error_out;
-       }
 
-       /* copy any maps to caller's array and return any error. */
+       /*
+        * Copy any maps to caller's array and return any error.
+        */
        if (nimaps == 0) {
                error = (ENOSPC);
                goto error_out;
        }
 
-       *ret_imap = imap[0];
+       *ret_imap = imap;
        *nmaps = 1;
        if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
                 cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
@@ -530,10 +489,11 @@ xfs_iomap_write_direct(
         }
        return 0;
 
- error0:       /* Cancel bmap, unlock inode, and cancel trans */
+error0:        /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
        xfs_bmap_cancel(&free_list);
+       XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
 
- error1:       /* Just cancel transaction */
+error1:        /* Just cancel transaction */
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
        *nmaps = 0;     /* nothing set-up here */