]> Pileus Git - ~andy/linux/blob - fs/xfs/xfs_attr_remote.c
Linux 3.14
[~andy/linux] / fs / xfs / xfs_attr_remote.c
1 /*
2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3  * Copyright (c) 2013 Red Hat, Inc.
4  * All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it would be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write the Free Software Foundation,
17  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 #include "xfs.h"
20 #include "xfs_fs.h"
21 #include "xfs_shared.h"
22 #include "xfs_format.h"
23 #include "xfs_log_format.h"
24 #include "xfs_trans_resv.h"
25 #include "xfs_bit.h"
26 #include "xfs_sb.h"
27 #include "xfs_ag.h"
28 #include "xfs_mount.h"
29 #include "xfs_da_format.h"
30 #include "xfs_da_btree.h"
31 #include "xfs_inode.h"
32 #include "xfs_alloc.h"
33 #include "xfs_trans.h"
34 #include "xfs_inode_item.h"
35 #include "xfs_bmap.h"
36 #include "xfs_bmap_util.h"
37 #include "xfs_attr.h"
38 #include "xfs_attr_leaf.h"
39 #include "xfs_attr_remote.h"
40 #include "xfs_trans_space.h"
41 #include "xfs_trace.h"
42 #include "xfs_cksum.h"
43 #include "xfs_buf_item.h"
44 #include "xfs_error.h"
45
46 #define ATTR_RMTVALUE_MAPSIZE   1       /* # of map entries at once */
47
48 /*
49  * Each contiguous block has a header, so it is not just a simple attribute
50  * length to FSB conversion.
51  */
52 int
53 xfs_attr3_rmt_blocks(
54         struct xfs_mount *mp,
55         int             attrlen)
56 {
57         if (xfs_sb_version_hascrc(&mp->m_sb)) {
58                 int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
59                 return (attrlen + buflen - 1) / buflen;
60         }
61         return XFS_B_TO_FSB(mp, attrlen);
62 }
63
64 /*
65  * Checking of the remote attribute header is split into two parts. The verifier
66  * does CRC, location and bounds checking, the unpacking function checks the
67  * attribute parameters and owner.
68  */
69 static bool
70 xfs_attr3_rmt_hdr_ok(
71         struct xfs_mount        *mp,
72         void                    *ptr,
73         xfs_ino_t               ino,
74         uint32_t                offset,
75         uint32_t                size,
76         xfs_daddr_t             bno)
77 {
78         struct xfs_attr3_rmt_hdr *rmt = ptr;
79
80         if (bno != be64_to_cpu(rmt->rm_blkno))
81                 return false;
82         if (offset != be32_to_cpu(rmt->rm_offset))
83                 return false;
84         if (size != be32_to_cpu(rmt->rm_bytes))
85                 return false;
86         if (ino != be64_to_cpu(rmt->rm_owner))
87                 return false;
88
89         /* ok */
90         return true;
91 }
92
93 static bool
94 xfs_attr3_rmt_verify(
95         struct xfs_mount        *mp,
96         void                    *ptr,
97         int                     fsbsize,
98         xfs_daddr_t             bno)
99 {
100         struct xfs_attr3_rmt_hdr *rmt = ptr;
101
102         if (!xfs_sb_version_hascrc(&mp->m_sb))
103                 return false;
104         if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC))
105                 return false;
106         if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid))
107                 return false;
108         if (be64_to_cpu(rmt->rm_blkno) != bno)
109                 return false;
110         if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
111                 return false;
112         if (be32_to_cpu(rmt->rm_offset) +
113                                 be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
114                 return false;
115         if (rmt->rm_owner == 0)
116                 return false;
117
118         return true;
119 }
120
121 static void
122 xfs_attr3_rmt_read_verify(
123         struct xfs_buf  *bp)
124 {
125         struct xfs_mount *mp = bp->b_target->bt_mount;
126         char            *ptr;
127         int             len;
128         bool            corrupt = false;
129         xfs_daddr_t     bno;
130
131         /* no verification of non-crc buffers */
132         if (!xfs_sb_version_hascrc(&mp->m_sb))
133                 return;
134
135         ptr = bp->b_addr;
136         bno = bp->b_bn;
137         len = BBTOB(bp->b_length);
138         ASSERT(len >= XFS_LBSIZE(mp));
139
140         while (len > 0) {
141                 if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
142                                       XFS_ATTR3_RMT_CRC_OFF)) {
143                         corrupt = true;
144                         break;
145                 }
146                 if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
147                         corrupt = true;
148                         break;
149                 }
150                 len -= XFS_LBSIZE(mp);
151                 ptr += XFS_LBSIZE(mp);
152                 bno += mp->m_bsize;
153         }
154
155         if (corrupt) {
156                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
157                 xfs_buf_ioerror(bp, EFSCORRUPTED);
158         } else
159                 ASSERT(len == 0);
160 }
161
162 static void
163 xfs_attr3_rmt_write_verify(
164         struct xfs_buf  *bp)
165 {
166         struct xfs_mount *mp = bp->b_target->bt_mount;
167         struct xfs_buf_log_item *bip = bp->b_fspriv;
168         char            *ptr;
169         int             len;
170         xfs_daddr_t     bno;
171
172         /* no verification of non-crc buffers */
173         if (!xfs_sb_version_hascrc(&mp->m_sb))
174                 return;
175
176         ptr = bp->b_addr;
177         bno = bp->b_bn;
178         len = BBTOB(bp->b_length);
179         ASSERT(len >= XFS_LBSIZE(mp));
180
181         while (len > 0) {
182                 if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
183                         XFS_CORRUPTION_ERROR(__func__,
184                                             XFS_ERRLEVEL_LOW, mp, bp->b_addr);
185                         xfs_buf_ioerror(bp, EFSCORRUPTED);
186                         return;
187                 }
188                 if (bip) {
189                         struct xfs_attr3_rmt_hdr *rmt;
190
191                         rmt = (struct xfs_attr3_rmt_hdr *)ptr;
192                         rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
193                 }
194                 xfs_update_cksum(ptr, XFS_LBSIZE(mp), XFS_ATTR3_RMT_CRC_OFF);
195
196                 len -= XFS_LBSIZE(mp);
197                 ptr += XFS_LBSIZE(mp);
198                 bno += mp->m_bsize;
199         }
200         ASSERT(len == 0);
201 }
202
203 const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
204         .verify_read = xfs_attr3_rmt_read_verify,
205         .verify_write = xfs_attr3_rmt_write_verify,
206 };
207
208 STATIC int
209 xfs_attr3_rmt_hdr_set(
210         struct xfs_mount        *mp,
211         void                    *ptr,
212         xfs_ino_t               ino,
213         uint32_t                offset,
214         uint32_t                size,
215         xfs_daddr_t             bno)
216 {
217         struct xfs_attr3_rmt_hdr *rmt = ptr;
218
219         if (!xfs_sb_version_hascrc(&mp->m_sb))
220                 return 0;
221
222         rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC);
223         rmt->rm_offset = cpu_to_be32(offset);
224         rmt->rm_bytes = cpu_to_be32(size);
225         uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid);
226         rmt->rm_owner = cpu_to_be64(ino);
227         rmt->rm_blkno = cpu_to_be64(bno);
228
229         return sizeof(struct xfs_attr3_rmt_hdr);
230 }
231
232 /*
233  * Helper functions to copy attribute data in and out of the one disk extents
234  */
235 STATIC int
236 xfs_attr_rmtval_copyout(
237         struct xfs_mount *mp,
238         struct xfs_buf  *bp,
239         xfs_ino_t       ino,
240         int             *offset,
241         int             *valuelen,
242         __uint8_t       **dst)
243 {
244         char            *src = bp->b_addr;
245         xfs_daddr_t     bno = bp->b_bn;
246         int             len = BBTOB(bp->b_length);
247
248         ASSERT(len >= XFS_LBSIZE(mp));
249
250         while (len > 0 && *valuelen > 0) {
251                 int hdr_size = 0;
252                 int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
253
254                 byte_cnt = min(*valuelen, byte_cnt);
255
256                 if (xfs_sb_version_hascrc(&mp->m_sb)) {
257                         if (!xfs_attr3_rmt_hdr_ok(mp, src, ino, *offset,
258                                                   byte_cnt, bno)) {
259                                 xfs_alert(mp,
260 "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
261                                         bno, *offset, byte_cnt, ino);
262                                 return EFSCORRUPTED;
263                         }
264                         hdr_size = sizeof(struct xfs_attr3_rmt_hdr);
265                 }
266
267                 memcpy(*dst, src + hdr_size, byte_cnt);
268
269                 /* roll buffer forwards */
270                 len -= XFS_LBSIZE(mp);
271                 src += XFS_LBSIZE(mp);
272                 bno += mp->m_bsize;
273
274                 /* roll attribute data forwards */
275                 *valuelen -= byte_cnt;
276                 *dst += byte_cnt;
277                 *offset += byte_cnt;
278         }
279         return 0;
280 }
281
282 STATIC void
283 xfs_attr_rmtval_copyin(
284         struct xfs_mount *mp,
285         struct xfs_buf  *bp,
286         xfs_ino_t       ino,
287         int             *offset,
288         int             *valuelen,
289         __uint8_t       **src)
290 {
291         char            *dst = bp->b_addr;
292         xfs_daddr_t     bno = bp->b_bn;
293         int             len = BBTOB(bp->b_length);
294
295         ASSERT(len >= XFS_LBSIZE(mp));
296
297         while (len > 0 && *valuelen > 0) {
298                 int hdr_size;
299                 int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
300
301                 byte_cnt = min(*valuelen, byte_cnt);
302                 hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
303                                                  byte_cnt, bno);
304
305                 memcpy(dst + hdr_size, *src, byte_cnt);
306
307                 /*
308                  * If this is the last block, zero the remainder of it.
309                  * Check that we are actually the last block, too.
310                  */
311                 if (byte_cnt + hdr_size < XFS_LBSIZE(mp)) {
312                         ASSERT(*valuelen - byte_cnt == 0);
313                         ASSERT(len == XFS_LBSIZE(mp));
314                         memset(dst + hdr_size + byte_cnt, 0,
315                                         XFS_LBSIZE(mp) - hdr_size - byte_cnt);
316                 }
317
318                 /* roll buffer forwards */
319                 len -= XFS_LBSIZE(mp);
320                 dst += XFS_LBSIZE(mp);
321                 bno += mp->m_bsize;
322
323                 /* roll attribute data forwards */
324                 *valuelen -= byte_cnt;
325                 *src += byte_cnt;
326                 *offset += byte_cnt;
327         }
328 }
329
330 /*
331  * Read the value associated with an attribute from the out-of-line buffer
332  * that we stored it in.
333  */
334 int
335 xfs_attr_rmtval_get(
336         struct xfs_da_args      *args)
337 {
338         struct xfs_bmbt_irec    map[ATTR_RMTVALUE_MAPSIZE];
339         struct xfs_mount        *mp = args->dp->i_mount;
340         struct xfs_buf          *bp;
341         xfs_dablk_t             lblkno = args->rmtblkno;
342         __uint8_t               *dst = args->value;
343         int                     valuelen = args->valuelen;
344         int                     nmap;
345         int                     error;
346         int                     blkcnt = args->rmtblkcnt;
347         int                     i;
348         int                     offset = 0;
349
350         trace_xfs_attr_rmtval_get(args);
351
352         ASSERT(!(args->flags & ATTR_KERNOVAL));
353
354         while (valuelen > 0) {
355                 nmap = ATTR_RMTVALUE_MAPSIZE;
356                 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
357                                        blkcnt, map, &nmap,
358                                        XFS_BMAPI_ATTRFORK);
359                 if (error)
360                         return error;
361                 ASSERT(nmap >= 1);
362
363                 for (i = 0; (i < nmap) && (valuelen > 0); i++) {
364                         xfs_daddr_t     dblkno;
365                         int             dblkcnt;
366
367                         ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
368                                (map[i].br_startblock != HOLESTARTBLOCK));
369                         dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
370                         dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
371                         error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
372                                                    dblkno, dblkcnt, 0, &bp,
373                                                    &xfs_attr3_rmt_buf_ops);
374                         if (error)
375                                 return error;
376
377                         error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
378                                                         &offset, &valuelen,
379                                                         &dst);
380                         xfs_buf_relse(bp);
381                         if (error)
382                                 return error;
383
384                         /* roll attribute extent map forwards */
385                         lblkno += map[i].br_blockcount;
386                         blkcnt -= map[i].br_blockcount;
387                 }
388         }
389         ASSERT(valuelen == 0);
390         return 0;
391 }
392
393 /*
394  * Write the value associated with an attribute into the out-of-line buffer
395  * that we have defined for it.
396  */
397 int
398 xfs_attr_rmtval_set(
399         struct xfs_da_args      *args)
400 {
401         struct xfs_inode        *dp = args->dp;
402         struct xfs_mount        *mp = dp->i_mount;
403         struct xfs_bmbt_irec    map;
404         xfs_dablk_t             lblkno;
405         xfs_fileoff_t           lfileoff = 0;
406         __uint8_t               *src = args->value;
407         int                     blkcnt;
408         int                     valuelen;
409         int                     nmap;
410         int                     error;
411         int                     offset = 0;
412
413         trace_xfs_attr_rmtval_set(args);
414
415         /*
416          * Find a "hole" in the attribute address space large enough for
417          * us to drop the new attribute's value into. Because CRC enable
418          * attributes have headers, we can't just do a straight byte to FSB
419          * conversion and have to take the header space into account.
420          */
421         blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
422         error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
423                                                    XFS_ATTR_FORK);
424         if (error)
425                 return error;
426
427         args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
428         args->rmtblkcnt = blkcnt;
429
430         /*
431          * Roll through the "value", allocating blocks on disk as required.
432          */
433         while (blkcnt > 0) {
434                 int     committed;
435
436                 /*
437                  * Allocate a single extent, up to the size of the value.
438                  */
439                 xfs_bmap_init(args->flist, args->firstblock);
440                 nmap = 1;
441                 error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
442                                   blkcnt,
443                                   XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
444                                   args->firstblock, args->total, &map, &nmap,
445                                   args->flist);
446                 if (!error) {
447                         error = xfs_bmap_finish(&args->trans, args->flist,
448                                                 &committed);
449                 }
450                 if (error) {
451                         ASSERT(committed);
452                         args->trans = NULL;
453                         xfs_bmap_cancel(args->flist);
454                         return(error);
455                 }
456
457                 /*
458                  * bmap_finish() may have committed the last trans and started
459                  * a new one.  We need the inode to be in all transactions.
460                  */
461                 if (committed)
462                         xfs_trans_ijoin(args->trans, dp, 0);
463
464                 ASSERT(nmap == 1);
465                 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
466                        (map.br_startblock != HOLESTARTBLOCK));
467                 lblkno += map.br_blockcount;
468                 blkcnt -= map.br_blockcount;
469
470                 /*
471                  * Start the next trans in the chain.
472                  */
473                 error = xfs_trans_roll(&args->trans, dp);
474                 if (error)
475                         return (error);
476         }
477
478         /*
479          * Roll through the "value", copying the attribute value to the
480          * already-allocated blocks.  Blocks are written synchronously
481          * so that we can know they are all on disk before we turn off
482          * the INCOMPLETE flag.
483          */
484         lblkno = args->rmtblkno;
485         blkcnt = args->rmtblkcnt;
486         valuelen = args->valuelen;
487         while (valuelen > 0) {
488                 struct xfs_buf  *bp;
489                 xfs_daddr_t     dblkno;
490                 int             dblkcnt;
491
492                 ASSERT(blkcnt > 0);
493
494                 xfs_bmap_init(args->flist, args->firstblock);
495                 nmap = 1;
496                 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
497                                        blkcnt, &map, &nmap,
498                                        XFS_BMAPI_ATTRFORK);
499                 if (error)
500                         return(error);
501                 ASSERT(nmap == 1);
502                 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
503                        (map.br_startblock != HOLESTARTBLOCK));
504
505                 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
506                 dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
507
508                 bp = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, 0);
509                 if (!bp)
510                         return ENOMEM;
511                 bp->b_ops = &xfs_attr3_rmt_buf_ops;
512
513                 xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
514                                        &valuelen, &src);
515
516                 error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
517                 xfs_buf_relse(bp);
518                 if (error)
519                         return error;
520
521
522                 /* roll attribute extent map forwards */
523                 lblkno += map.br_blockcount;
524                 blkcnt -= map.br_blockcount;
525         }
526         ASSERT(valuelen == 0);
527         return 0;
528 }
529
530 /*
531  * Remove the value associated with an attribute by deleting the
532  * out-of-line buffer that it is stored on.
533  */
534 int
535 xfs_attr_rmtval_remove(
536         struct xfs_da_args      *args)
537 {
538         struct xfs_mount        *mp = args->dp->i_mount;
539         xfs_dablk_t             lblkno;
540         int                     blkcnt;
541         int                     error;
542         int                     done;
543
544         trace_xfs_attr_rmtval_remove(args);
545
546         /*
547          * Roll through the "value", invalidating the attribute value's blocks.
548          */
549         lblkno = args->rmtblkno;
550         blkcnt = args->rmtblkcnt;
551         while (blkcnt > 0) {
552                 struct xfs_bmbt_irec    map;
553                 struct xfs_buf          *bp;
554                 xfs_daddr_t             dblkno;
555                 int                     dblkcnt;
556                 int                     nmap;
557
558                 /*
559                  * Try to remember where we decided to put the value.
560                  */
561                 nmap = 1;
562                 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
563                                        blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
564                 if (error)
565                         return(error);
566                 ASSERT(nmap == 1);
567                 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
568                        (map.br_startblock != HOLESTARTBLOCK));
569
570                 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
571                 dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
572
573                 /*
574                  * If the "remote" value is in the cache, remove it.
575                  */
576                 bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
577                 if (bp) {
578                         xfs_buf_stale(bp);
579                         xfs_buf_relse(bp);
580                         bp = NULL;
581                 }
582
583                 lblkno += map.br_blockcount;
584                 blkcnt -= map.br_blockcount;
585         }
586
587         /*
588          * Keep de-allocating extents until the remote-value region is gone.
589          */
590         lblkno = args->rmtblkno;
591         blkcnt = args->rmtblkcnt;
592         done = 0;
593         while (!done) {
594                 int committed;
595
596                 xfs_bmap_init(args->flist, args->firstblock);
597                 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
598                                     XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
599                                     1, args->firstblock, args->flist,
600                                     &done);
601                 if (!error) {
602                         error = xfs_bmap_finish(&args->trans, args->flist,
603                                                 &committed);
604                 }
605                 if (error) {
606                         ASSERT(committed);
607                         args->trans = NULL;
608                         xfs_bmap_cancel(args->flist);
609                         return error;
610                 }
611
612                 /*
613                  * bmap_finish() may have committed the last trans and started
614                  * a new one.  We need the inode to be in all transactions.
615                  */
616                 if (committed)
617                         xfs_trans_ijoin(args->trans, args->dp, 0);
618
619                 /*
620                  * Close out trans and start the next one in the chain.
621                  */
622                 error = xfs_trans_roll(&args->trans, args->dp);
623                 if (error)
624                         return (error);
625         }
626         return(0);
627 }