commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / fs / xfs / linux / xfs_iomap.c
1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include "xfs.h"
34
35 #include "xfs_fs.h"
36 #include "xfs_inum.h"
37 #include "xfs_log.h"
38 #include "xfs_trans.h"
39 #include "xfs_sb.h"
40 #include "xfs_ag.h"
41 #include "xfs_dir.h"
42 #include "xfs_dir2.h"
43 #include "xfs_alloc.h"
44 #include "xfs_dmapi.h"
45 #include "xfs_quota.h"
46 #include "xfs_mount.h"
47 #include "xfs_alloc_btree.h"
48 #include "xfs_bmap_btree.h"
49 #include "xfs_ialloc_btree.h"
50 #include "xfs_btree.h"
51 #include "xfs_ialloc.h"
52 #include "xfs_attr_sf.h"
53 #include "xfs_dir_sf.h"
54 #include "xfs_dir2_sf.h"
55 #include "xfs_dinode.h"
56 #include "xfs_inode.h"
57 #include "xfs_bmap.h"
58 #include "xfs_bit.h"
59 #include "xfs_rtalloc.h"
60 #include "xfs_error.h"
61 #include "xfs_itable.h"
62 #include "xfs_rw.h"
63 #include "xfs_acl.h"
64 #include "xfs_cap.h"
65 #include "xfs_mac.h"
66 #include "xfs_attr.h"
67 #include "xfs_buf_item.h"
68 #include "xfs_trans_space.h"
69 #include "xfs_utils.h"
70
71 #define XFS_WRITEIO_ALIGN(mp,off)       (((off) >> mp->m_writeio_log) \
72                                                 << mp->m_writeio_log)
73 #define XFS_STRAT_WRITE_IMAPS   2
74 #define XFS_WRITE_IMAPS         XFS_BMAP_MAX_NMAP
75
76 STATIC int
77 _xfs_imap_to_bmap(
78         xfs_iocore_t    *io,
79         xfs_off_t       offset,
80         int             new,
81         xfs_bmbt_irec_t *imap,
82         page_buf_bmap_t *pbmapp,
83         int             imaps,                  /* Number of imap entries */
84         int             pbmaps)                 /* Number of pbmap entries */
85 {
86         xfs_mount_t     *mp;
87         xfs_fsize_t     nisize;
88         int             pbm;
89         xfs_fsblock_t   start_block;
90
91         mp = io->io_mount;
92         nisize = XFS_SIZE(mp, io);
93         if (io->io_new_size > nisize)
94                 nisize = io->io_new_size;
95
96         for (pbm = 0; imaps && pbm < pbmaps; imaps--, pbmapp++, imap++, pbm++) {
97                 pbmapp->pbm_target = io->io_flags & XFS_IOCORE_RT ?
98                         mp->m_rtdev_targp : mp->m_ddev_targp;
99                 pbmapp->pbm_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
100                 pbmapp->pbm_delta = offset - pbmapp->pbm_offset;
101                 pbmapp->pbm_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
102                 pbmapp->pbm_flags = 0;
103
104                 start_block = imap->br_startblock;
105                 if (start_block == HOLESTARTBLOCK) {
106                         pbmapp->pbm_bn = PAGE_BUF_DADDR_NULL;
107                         pbmapp->pbm_flags = PBMF_HOLE;
108                 } else if (start_block == DELAYSTARTBLOCK) {
109                         pbmapp->pbm_bn = PAGE_BUF_DADDR_NULL;
110                         pbmapp->pbm_flags = PBMF_DELAY;
111                 } else {
112                         pbmapp->pbm_bn = XFS_FSB_TO_DB_IO(io, start_block);
113                         if (ISUNWRITTEN(imap))
114                                 pbmapp->pbm_flags |= PBMF_UNWRITTEN;
115                 }
116
117                 if ((pbmapp->pbm_offset + pbmapp->pbm_bsize) >= nisize) {
118                         pbmapp->pbm_flags |= PBMF_EOF;
119                 }
120
121                 if (new)
122                         pbmapp->pbm_flags |= PBMF_NEW;
123
124                 offset += pbmapp->pbm_bsize - pbmapp->pbm_delta;
125         }
126         return pbm;     /* Return the number filled */
127 }
128
129 int
130 xfs_iomap(
131         xfs_iocore_t    *io,
132         xfs_off_t       offset,
133         ssize_t         count,
134         int             flags,
135         page_buf_bmap_t *pbmapp,
136         int             *npbmaps)
137 {
138         xfs_mount_t     *mp = io->io_mount;
139         xfs_fileoff_t   offset_fsb, end_fsb;
140         int             error = 0;
141         int             new = 0;
142         int             lockmode = 0;
143         xfs_bmbt_irec_t imap;
144         int             nimaps = 1;
145         int             bmap_flags = 0;
146
147         if (XFS_FORCED_SHUTDOWN(mp))
148                 return -XFS_ERROR(EIO);
149
150         switch (flags &
151                 (BMAP_READ | BMAP_WRITE | BMAP_ALLOCATE |
152                  BMAP_UNWRITTEN | BMAP_DEVICE)) {
153         case BMAP_READ:
154                 lockmode = XFS_LCK_MAP_SHARED(mp, io);
155                 bmap_flags = XFS_BMAPI_ENTIRE;
156                 if (flags & BMAP_IGNSTATE)
157                         bmap_flags |= XFS_BMAPI_IGSTATE;
158                 break;
159         case PBF_WRITE:
160                 lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
161                 bmap_flags = 0;
162                 XFS_ILOCK(mp, io, lockmode);
163                 break;
164         case BMAP_ALLOCATE:
165                 lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
166                 bmap_flags = XFS_BMAPI_ENTIRE;
167                 /* Attempt non-blocking lock */
168                 if (flags & BMAP_TRYLOCK) {
169                         if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
170                                 return XFS_ERROR(EAGAIN);
171                 } else {
172                         XFS_ILOCK(mp, io, lockmode);
173                 }
174                 break;
175         case BMAP_UNWRITTEN:
176                 goto phase2;
177         case BMAP_DEVICE:
178                 lockmode = XFS_LCK_MAP_SHARED(mp, io);
179                 pbmapp->pbm_target = io->io_flags & XFS_IOCORE_RT ?
180                         mp->m_rtdev_targp : mp->m_ddev_targp;
181                 error = 0;
182                 *npbmaps = 1;
183                 goto out;
184         default:
185                 BUG();
186         }
187
188         ASSERT(offset <= mp->m_maxioffset);
189         if ((xfs_fsize_t)offset + count > mp->m_maxioffset)
190                 count = mp->m_maxioffset - offset;
191         end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
192         offset_fsb = XFS_B_TO_FSBT(mp, offset);
193
194         error = XFS_BMAPI(mp, NULL, io, offset_fsb,
195                         (xfs_filblks_t)(end_fsb - offset_fsb) ,
196                         bmap_flags,  NULL, 0, &imap,
197                         &nimaps, NULL);
198
199         if (error)
200                 goto out;
201
202 phase2:
203         switch (flags & (BMAP_WRITE|BMAP_ALLOCATE|BMAP_UNWRITTEN)) {
204         case BMAP_WRITE:
205                 /* If we found an extent, return it */
206                 if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
207                         break;
208
209                 if (flags & (BMAP_DIRECT|BMAP_MMAP)) {
210                         error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
211                                         count, flags, &imap, &nimaps, nimaps);
212                 } else {
213                         error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
214                                         flags, &imap, &nimaps);
215                 }
216                 new = 1;
217                 break;
218         case BMAP_ALLOCATE:
219                 /* If we found an extent, return it */
220                 XFS_IUNLOCK(mp, io, lockmode);
221                 lockmode = 0;
222
223                 if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
224                         break;
225
226                 error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
227                 break;
228         case BMAP_UNWRITTEN:
229                 lockmode = 0;
230                 error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
231                 nimaps = 0;
232                 break;
233         }
234
235         if (nimaps) {
236                 *npbmaps = _xfs_imap_to_bmap(io, offset, new, &imap,
237                                         pbmapp, nimaps, *npbmaps);
238         } else if (npbmaps) {
239                 *npbmaps = 0;
240         }
241
242 out:
243         if (lockmode)
244                 XFS_IUNLOCK(mp, io, lockmode);
245         return XFS_ERROR(error);
246 }
247
248 STATIC int
249 xfs_flush_space(
250         xfs_inode_t     *ip,
251         int             *fsynced,
252         int             *ioflags)
253 {
254         vnode_t         *vp = XFS_ITOV(ip);
255
256         switch (*fsynced) {
257         case 0:
258                 if (ip->i_delayed_blks) {
259                         xfs_iunlock(ip, XFS_ILOCK_EXCL);
260                         filemap_fdatawrite(LINVFS_GET_IP(vp)->i_mapping);
261                         xfs_ilock(ip, XFS_ILOCK_EXCL);
262                         *fsynced = 1;
263                 } else {
264                         *ioflags |= BMAP_SYNC;
265                         *fsynced = 2;
266                 }
267                 return 0;
268         case 1:
269                 *fsynced = 2;
270                 *ioflags |= BMAP_SYNC;
271                 return 0;
272         case 2:
273                 xfs_iunlock(ip, XFS_ILOCK_EXCL);
274                 sync_blockdev(vp->v_vfsp->vfs_super->s_bdev);
275                 xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
276                                                 XFS_LOG_FORCE|XFS_LOG_SYNC);
277                 xfs_ilock(ip, XFS_ILOCK_EXCL);
278                 *fsynced = 3;
279                 return 0;
280         }
281         return 1;
282 }
283
284 int
285 xfs_iomap_write_direct(
286         xfs_inode_t     *ip,
287         loff_t          offset,
288         size_t          count,
289         int             flags,
290         xfs_bmbt_irec_t *ret_imap,
291         int             *nmaps,
292         int             found)
293 {
294         xfs_mount_t     *mp = ip->i_mount;
295         xfs_iocore_t    *io = &ip->i_iocore;
296         xfs_fileoff_t   offset_fsb;
297         xfs_fileoff_t   last_fsb;
298         xfs_filblks_t   count_fsb;
299         xfs_fsize_t     isize;
300         xfs_fsblock_t   firstfsb;
301         int             nimaps, maps;
302         int             error;
303         int             bmapi_flag;
304         int             rt;
305         xfs_trans_t     *tp;
306         xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
307         xfs_bmap_free_t free_list;
308         int             aeof;
309         xfs_filblks_t   datablocks;
310         int             committed;
311         int             numrtextents;
312         uint            resblks;
313
314         /*
315          * Make sure that the dquots are there. This doesn't hold
316          * the ilock across a disk read.
317          */
318
319         error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
320         if (error)
321                 return XFS_ERROR(error);
322
323         maps = min(XFS_WRITE_IMAPS, *nmaps);
324         nimaps = maps;
325
326         isize = ip->i_d.di_size;
327         aeof = (offset + count) > isize;
328
329         if (io->io_new_size > isize)
330                 isize = io->io_new_size;
331
332         offset_fsb = XFS_B_TO_FSBT(mp, offset);
333         last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
334         count_fsb = last_fsb - offset_fsb;
335         if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) {
336                 xfs_fileoff_t   map_last_fsb;
337
338                 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
339
340                 if (map_last_fsb < last_fsb) {
341                         last_fsb = map_last_fsb;
342                         count_fsb = last_fsb - offset_fsb;
343                 }
344                 ASSERT(count_fsb > 0);
345         }
346
347         /*
348          * determine if reserving space on
349          * the data or realtime partition.
350          */
351         if ((rt = XFS_IS_REALTIME_INODE(ip))) {
352                 int     sbrtextsize, iprtextsize;
353
354                 sbrtextsize = mp->m_sb.sb_rextsize;
355                 iprtextsize =
356                         ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
357                 numrtextents = (count_fsb + iprtextsize - 1);
358                 do_div(numrtextents, sbrtextsize);
359                 datablocks = 0;
360         } else {
361                 datablocks = count_fsb;
362                 numrtextents = 0;
363         }
364
365         /*
366          * allocate and setup the transaction
367          */
368         xfs_iunlock(ip, XFS_ILOCK_EXCL);
369         tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
370
371         resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
372
373         error = xfs_trans_reserve(tp, resblks,
374                         XFS_WRITE_LOG_RES(mp), numrtextents,
375                         XFS_TRANS_PERM_LOG_RES,
376                         XFS_WRITE_LOG_COUNT);
377
378         /*
379          * check for running out of space
380          */
381         if (error)
382                 /*
383                  * Free the transaction structure.
384                  */
385                 xfs_trans_cancel(tp, 0);
386
387         xfs_ilock(ip, XFS_ILOCK_EXCL);
388
389         if (error)
390                 goto error_out; /* Don't return in above if .. trans ..,
391                                         need lock to return */
392
393         if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
394                 error = (EDQUOT);
395                 goto error1;
396         }
397         nimaps = 1;
398
399         bmapi_flag = XFS_BMAPI_WRITE;
400         xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
401         xfs_trans_ihold(tp, ip);
402
403         if (!(flags & BMAP_MMAP) && (offset < ip->i_d.di_size || rt))
404                 bmapi_flag |= XFS_BMAPI_PREALLOC;
405
406         /*
407          * issue the bmapi() call to allocate the blocks
408          */
409         XFS_BMAP_INIT(&free_list, &firstfsb);
410         imapp = &imap[0];
411         error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
412                 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
413         if (error) {
414                 goto error0;
415         }
416
417         /*
418          * complete the transaction
419          */
420
421         error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
422         if (error) {
423                 goto error0;
424         }
425
426         error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
427         if (error) {
428                 goto error_out;
429         }
430
431         /* copy any maps to caller's array and return any error. */
432         if (nimaps == 0) {
433                 error = (ENOSPC);
434                 goto error_out;
435         }
436
437         *ret_imap = imap[0];
438         *nmaps = 1;
439         return 0;
440
441  error0:        /* Cancel bmap, unlock inode, and cancel trans */
442         xfs_bmap_cancel(&free_list);
443
444  error1:        /* Just cancel transaction */
445         xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
446         *nmaps = 0;     /* nothing set-up here */
447
448 error_out:
449         return XFS_ERROR(error);
450 }
451
452 int
453 xfs_iomap_write_delay(
454         xfs_inode_t     *ip,
455         loff_t          offset,
456         size_t          count,
457         int             ioflag,
458         xfs_bmbt_irec_t *ret_imap,
459         int             *nmaps)
460 {
461         xfs_mount_t     *mp = ip->i_mount;
462         xfs_iocore_t    *io = &ip->i_iocore;
463         xfs_fileoff_t   offset_fsb;
464         xfs_fileoff_t   last_fsb;
465         xfs_fsize_t     isize;
466         xfs_fsblock_t   firstblock;
467         int             nimaps;
468         int             error;
469         xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
470         int             aeof;
471         int             fsynced = 0;
472
473         ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
474
475         /*
476          * Make sure that the dquots are there. This doesn't hold
477          * the ilock across a disk read.
478          */
479
480         error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
481         if (error)
482                 return XFS_ERROR(error);
483
484 retry:
485         isize = ip->i_d.di_size;
486         if (io->io_new_size > isize) {
487                 isize = io->io_new_size;
488         }
489
490         aeof = 0;
491         offset_fsb = XFS_B_TO_FSBT(mp, offset);
492         last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
493         /*
494          * If the caller is doing a write at the end of the file,
495          * then extend the allocation (and the buffer used for the write)
496          * out to the file system's write iosize.  We clean up any extra
497          * space left over when the file is closed in xfs_inactive().
498          *
499          * We don't bother with this for sync writes, because we need
500          * to minimize the amount we write for good performance.
501          */
502         if (!(ioflag & BMAP_SYNC) && ((offset + count) > ip->i_d.di_size)) {
503                 xfs_off_t       aligned_offset;
504                 unsigned int    iosize;
505                 xfs_fileoff_t   ioalign;
506
507                 iosize = mp->m_writeio_blocks;
508                 aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
509                 ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
510                 last_fsb = ioalign + iosize;
511                 aeof = 1;
512         }
513
514         nimaps = XFS_WRITE_IMAPS;
515         firstblock = NULLFSBLOCK;
516
517         /*
518          * roundup the allocation request to m_dalign boundary if file size
519          * is greater that 512K and we are allocating past the allocation eof
520          */
521         if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) {
522                 int eof;
523                 xfs_fileoff_t new_last_fsb;
524                 new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
525                 error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
526                 if (error) {
527                         return error;
528                 }
529                 if (eof) {
530                         last_fsb = new_last_fsb;
531                 }
532         }
533
534         error = xfs_bmapi(NULL, ip, offset_fsb,
535                           (xfs_filblks_t)(last_fsb - offset_fsb),
536                           XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
537                           XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
538                           &nimaps, NULL);
539         /*
540          * This can be EDQUOT, if nimaps == 0
541          */
542         if (error && (error != ENOSPC)) {
543                 return XFS_ERROR(error);
544         }
545         /*
546          * If bmapi returned us nothing, and if we didn't get back EDQUOT,
547          * then we must have run out of space.
548          */
549
550         if (nimaps == 0) {
551                 if (xfs_flush_space(ip, &fsynced, &ioflag))
552                         return XFS_ERROR(ENOSPC);
553
554                 error = 0;
555                 goto retry;
556         }
557
558         *ret_imap = imap[0];
559         *nmaps = 1;
560         return 0;
561 }
562
563 /*
564  * Pass in a delayed allocate extent, convert it to real extents;
565  * return to the caller the extent we create which maps on top of
566  * the originating callers request.
567  *
568  * Called without a lock on the inode.
569  */
570 int
571 xfs_iomap_write_allocate(
572         xfs_inode_t     *ip,
573         xfs_bmbt_irec_t *map,
574         int             *retmap)
575 {
576         xfs_mount_t     *mp = ip->i_mount;
577         xfs_fileoff_t   offset_fsb, last_block;
578         xfs_fileoff_t   end_fsb, map_start_fsb;
579         xfs_fsblock_t   first_block;
580         xfs_bmap_free_t free_list;
581         xfs_filblks_t   count_fsb;
582         xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS];
583         xfs_trans_t     *tp;
584         int             i, nimaps, committed;
585         int             error = 0;
586         int             nres;
587
588         *retmap = 0;
589
590         /*
591          * Make sure that the dquots are there.
592          */
593
594         if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
595                 return XFS_ERROR(error);
596
597         offset_fsb = map->br_startoff;
598         count_fsb = map->br_blockcount;
599         map_start_fsb = offset_fsb;
600
601         XFS_STATS_ADD(xfsstats.xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
602
603         while (count_fsb != 0) {
604                 /*
605                  * Set up a transaction with which to allocate the
606                  * backing store for the file.  Do allocations in a
607                  * loop until we get some space in the range we are
608                  * interested in.  The other space that might be allocated
609                  * is in the delayed allocation extent on which we sit
610                  * but before our buffer starts.
611                  */
612
613                 nimaps = 0;
614                 while (nimaps == 0) {
615                         tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
616                         nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
617                         error = xfs_trans_reserve(tp, nres,
618                                         XFS_WRITE_LOG_RES(mp),
619                                         0, XFS_TRANS_PERM_LOG_RES,
620                                         XFS_WRITE_LOG_COUNT);
621
622                         if (error == ENOSPC) {
623                                 error = xfs_trans_reserve(tp, 0,
624                                                 XFS_WRITE_LOG_RES(mp),
625                                                 0,
626                                                 XFS_TRANS_PERM_LOG_RES,
627                                                 XFS_WRITE_LOG_COUNT);
628                         }
629                         if (error) {
630                                 xfs_trans_cancel(tp, 0);
631                                 return XFS_ERROR(error);
632                         }
633                         xfs_ilock(ip, XFS_ILOCK_EXCL);
634                         xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
635                         xfs_trans_ihold(tp, ip);
636
637                         XFS_BMAP_INIT(&free_list, &first_block);
638
639                         nimaps = XFS_STRAT_WRITE_IMAPS;
640                         /*
641                          * Ensure we don't go beyond eof - it is possible
642                          * the extents changed since we did the read call,
643                          * we dropped the ilock in the interim.
644                          */
645
646                         end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
647                         xfs_bmap_last_offset(NULL, ip, &last_block,
648                                 XFS_DATA_FORK);
649                         last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
650                         if ((map_start_fsb + count_fsb) > last_block) {
651                                 count_fsb = last_block - map_start_fsb;
652                                 if (count_fsb == 0) {
653                                         error = EAGAIN;
654                                         goto trans_cancel;
655                                 }
656                         }
657
658                         /* Go get the actual blocks */
659                         error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
660                                         XFS_BMAPI_WRITE, &first_block, 1,
661                                         imap, &nimaps, &free_list);
662
663                         if (error)
664                                 goto trans_cancel;
665
666                         error = xfs_bmap_finish(&tp, &free_list,
667                                         first_block, &committed);
668
669                         if (error)
670                                 goto trans_cancel;
671
672                         error = xfs_trans_commit(tp,
673                                         XFS_TRANS_RELEASE_LOG_RES, NULL);
674
675                         if (error)
676                                 goto error0;
677
678                         xfs_iunlock(ip, XFS_ILOCK_EXCL);
679                 }
680
681                 /*
682                  * See if we were able to allocate an extent that
683                  * covers at least part of the callers request
684                  */
685
686                 for (i = 0; i < nimaps; i++) {
687                         if ((map->br_startoff >= imap[i].br_startoff) &&
688                             (map->br_startoff < (imap[i].br_startoff +
689                                                  imap[i].br_blockcount))) {
690                                 *map = imap[i];
691                                 *retmap = 1;
692                                 XFS_STATS_INC(xfsstats.xs_xstrat_quick);
693                                 return 0;
694                         }
695                         count_fsb -= imap[i].br_blockcount;
696                 }
697
698                 /* So far we have not mapped the requested part of the
699                  * file, just surrounding data, try again.
700                  */
701                 nimaps--;
702                 offset_fsb = imap[nimaps].br_startoff +
703                              imap[nimaps].br_blockcount;
704                 map_start_fsb = offset_fsb;
705         }
706
707 trans_cancel:
708         xfs_bmap_cancel(&free_list);
709         xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
710 error0:
711         xfs_iunlock(ip, XFS_ILOCK_EXCL);
712         return XFS_ERROR(error);
713 }
714
715 int
716 xfs_iomap_write_unwritten(
717         xfs_inode_t     *ip,
718         loff_t          offset,
719         size_t          count)
720 {
721         xfs_mount_t     *mp = ip->i_mount;
722         xfs_trans_t     *tp;
723         xfs_fileoff_t   offset_fsb;
724         xfs_filblks_t   count_fsb;
725         xfs_filblks_t   numblks_fsb;
726         xfs_bmbt_irec_t imap;
727         int             committed;
728         int             error;
729         int             nres;
730         int             nimaps;
731         xfs_fsblock_t   firstfsb;
732         xfs_bmap_free_t free_list;
733
734         offset_fsb = XFS_B_TO_FSBT(mp, offset);
735         count_fsb = XFS_B_TO_FSB(mp, count);
736
737         do {
738                 nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
739
740                 /*
741                  * set up a transaction to convert the range of extents
742                  * from unwritten to real. Do allocations in a loop until
743                  * we have covered the range passed in.
744                  */
745
746                 tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
747                 error = xfs_trans_reserve(tp, nres,
748                                 XFS_WRITE_LOG_RES(mp), 0,
749                                 XFS_TRANS_PERM_LOG_RES,
750                                 XFS_WRITE_LOG_COUNT);
751                 if (error) {
752                         xfs_trans_cancel(tp, 0);
753                         goto error0;
754                 }
755
756                 xfs_ilock(ip, XFS_ILOCK_EXCL);
757                 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
758                 xfs_trans_ihold(tp, ip);
759
760                 /*
761                  * Modify the unwritten extent state of the buffer.
762                  */
763                 XFS_BMAP_INIT(&free_list, &firstfsb);
764                 nimaps = 1;
765                 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
766                                   XFS_BMAPI_WRITE, &firstfsb,
767                                   1, &imap, &nimaps, &free_list);
768                 if (error)
769                         goto error_on_bmapi_transaction;
770
771                 error = xfs_bmap_finish(&(tp), &(free_list),
772                                 firstfsb, &committed);
773                 if (error)
774                         goto error_on_bmapi_transaction;
775
776                 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
777                 xfs_iunlock(ip, XFS_ILOCK_EXCL);
778                 if (error)
779                         goto error0;
780
781                 if ((numblks_fsb = imap.br_blockcount) == 0) {
782                         /*
783                          * The numblks_fsb value should always get
784                          * smaller, otherwise the loop is stuck.
785                          */
786                         ASSERT(imap.br_blockcount);
787                         break;
788                 }
789                 offset_fsb += numblks_fsb;
790                 count_fsb -= numblks_fsb;
791         } while (count_fsb > 0);
792
793         return 0;
794
795 error_on_bmapi_transaction:
796         xfs_bmap_cancel(&free_list);
797         xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
798         xfs_iunlock(ip, XFS_ILOCK_EXCL);
799 error0:
800         return XFS_ERROR(error);
801 }