xfs: add CRC protection to remote attributes
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / 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_types.h"
22 #include "xfs_bit.h"
23 #include "xfs_log.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_mount.h"
28 #include "xfs_error.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_dinode.h"
32 #include "xfs_inode.h"
33 #include "xfs_alloc.h"
34 #include "xfs_inode_item.h"
35 #include "xfs_bmap.h"
36 #include "xfs_attr.h"
37 #include "xfs_attr_leaf.h"
38 #include "xfs_attr_remote.h"
39 #include "xfs_trans_space.h"
40 #include "xfs_trace.h"
41 #include "xfs_cksum.h"
42 #include "xfs_buf_item.h"
43
44 #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */
45
46 /*
47 * Each contiguous block has a header, so it is not just a simple attribute
48 * length to FSB conversion.
49 */
50 static int
51 xfs_attr3_rmt_blocks(
52 struct xfs_mount *mp,
53 int attrlen)
54 {
55 int fsblocks = 0;
56 int len = attrlen;
57
58 do {
59 fsblocks++;
60 len -= XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
61 } while (len > 0);
62
63 return fsblocks;
64 }
65
66 static bool
67 xfs_attr3_rmt_verify(
68 struct xfs_buf *bp)
69 {
70 struct xfs_mount *mp = bp->b_target->bt_mount;
71 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
72
73 if (!xfs_sb_version_hascrc(&mp->m_sb))
74 return false;
75 if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC))
76 return false;
77 if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid))
78 return false;
79 if (bp->b_bn != be64_to_cpu(rmt->rm_blkno))
80 return false;
81 if (be32_to_cpu(rmt->rm_offset) +
82 be32_to_cpu(rmt->rm_bytes) >= MAXPATHLEN)
83 return false;
84 if (rmt->rm_owner == 0)
85 return false;
86
87 return true;
88 }
89
90 static void
91 xfs_attr3_rmt_read_verify(
92 struct xfs_buf *bp)
93 {
94 struct xfs_mount *mp = bp->b_target->bt_mount;
95
96 /* no verification of non-crc buffers */
97 if (!xfs_sb_version_hascrc(&mp->m_sb))
98 return;
99
100 if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
101 XFS_ATTR3_RMT_CRC_OFF) ||
102 !xfs_attr3_rmt_verify(bp)) {
103 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
104 xfs_buf_ioerror(bp, EFSCORRUPTED);
105 }
106 }
107
108 static void
109 xfs_attr3_rmt_write_verify(
110 struct xfs_buf *bp)
111 {
112 struct xfs_mount *mp = bp->b_target->bt_mount;
113 struct xfs_buf_log_item *bip = bp->b_fspriv;
114
115 /* no verification of non-crc buffers */
116 if (!xfs_sb_version_hascrc(&mp->m_sb))
117 return;
118
119 if (!xfs_attr3_rmt_verify(bp)) {
120 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
121 xfs_buf_ioerror(bp, EFSCORRUPTED);
122 return;
123 }
124
125 if (bip) {
126 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
127 rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
128 }
129 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
130 XFS_ATTR3_RMT_CRC_OFF);
131 }
132
133 const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
134 .verify_read = xfs_attr3_rmt_read_verify,
135 .verify_write = xfs_attr3_rmt_write_verify,
136 };
137
138 static int
139 xfs_attr3_rmt_hdr_set(
140 struct xfs_mount *mp,
141 xfs_ino_t ino,
142 uint32_t offset,
143 uint32_t size,
144 struct xfs_buf *bp)
145 {
146 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
147
148 if (!xfs_sb_version_hascrc(&mp->m_sb))
149 return 0;
150
151 rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC);
152 rmt->rm_offset = cpu_to_be32(offset);
153 rmt->rm_bytes = cpu_to_be32(size);
154 uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid);
155 rmt->rm_owner = cpu_to_be64(ino);
156 rmt->rm_blkno = cpu_to_be64(bp->b_bn);
157 bp->b_ops = &xfs_attr3_rmt_buf_ops;
158
159 return sizeof(struct xfs_attr3_rmt_hdr);
160 }
161
162 /*
163 * Checking of the remote attribute header is split into two parts. the verifier
164 * does CRC, location and bounds checking, the unpacking function checks the
165 * attribute parameters and owner.
166 */
167 static bool
168 xfs_attr3_rmt_hdr_ok(
169 struct xfs_mount *mp,
170 xfs_ino_t ino,
171 uint32_t offset,
172 uint32_t size,
173 struct xfs_buf *bp)
174 {
175 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
176
177 if (offset != be32_to_cpu(rmt->rm_offset))
178 return false;
179 if (size != be32_to_cpu(rmt->rm_bytes))
180 return false;
181 if (ino != be64_to_cpu(rmt->rm_owner))
182 return false;
183
184 /* ok */
185 return true;
186
187 }
188
189 /*
190 * Read the value associated with an attribute from the out-of-line buffer
191 * that we stored it in.
192 */
193 int
194 xfs_attr_rmtval_get(
195 struct xfs_da_args *args)
196 {
197 struct xfs_bmbt_irec map[ATTR_RMTVALUE_MAPSIZE];
198 struct xfs_mount *mp = args->dp->i_mount;
199 struct xfs_buf *bp;
200 xfs_daddr_t dblkno;
201 xfs_dablk_t lblkno = args->rmtblkno;
202 void *dst = args->value;
203 int valuelen = args->valuelen;
204 int nmap;
205 int error;
206 int blkcnt;
207 int i;
208 int offset = 0;
209
210 trace_xfs_attr_rmtval_get(args);
211
212 ASSERT(!(args->flags & ATTR_KERNOVAL));
213
214 while (valuelen > 0) {
215 nmap = ATTR_RMTVALUE_MAPSIZE;
216 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
217 args->rmtblkcnt, map, &nmap,
218 XFS_BMAPI_ATTRFORK);
219 if (error)
220 return error;
221 ASSERT(nmap >= 1);
222
223 for (i = 0; (i < nmap) && (valuelen > 0); i++) {
224 int byte_cnt;
225 char *src;
226
227 ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
228 (map[i].br_startblock != HOLESTARTBLOCK));
229 dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
230 blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
231 error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
232 dblkno, blkcnt, 0, &bp,
233 &xfs_attr3_rmt_buf_ops);
234 if (error)
235 return error;
236
237 byte_cnt = min_t(int, valuelen, BBTOB(bp->b_length));
238 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, byte_cnt);
239
240 src = bp->b_addr;
241 if (xfs_sb_version_hascrc(&mp->m_sb)) {
242 if (!xfs_attr3_rmt_hdr_ok(mp, args->dp->i_ino,
243 offset, byte_cnt, bp)) {
244 xfs_alert(mp,
245 "remote attribute header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
246 offset, byte_cnt, args->dp->i_ino);
247 xfs_buf_relse(bp);
248 return EFSCORRUPTED;
249
250 }
251
252 src += sizeof(struct xfs_attr3_rmt_hdr);
253 }
254
255 memcpy(dst, src, byte_cnt);
256 xfs_buf_relse(bp);
257
258 offset += byte_cnt;
259 dst += byte_cnt;
260 valuelen -= byte_cnt;
261
262 lblkno += map[i].br_blockcount;
263 }
264 }
265 ASSERT(valuelen == 0);
266 return 0;
267 }
268
269 /*
270 * Write the value associated with an attribute into the out-of-line buffer
271 * that we have defined for it.
272 */
273 int
274 xfs_attr_rmtval_set(
275 struct xfs_da_args *args)
276 {
277 struct xfs_inode *dp = args->dp;
278 struct xfs_mount *mp = dp->i_mount;
279 struct xfs_bmbt_irec map;
280 struct xfs_buf *bp;
281 xfs_daddr_t dblkno;
282 xfs_dablk_t lblkno;
283 xfs_fileoff_t lfileoff = 0;
284 void *src = args->value;
285 int blkcnt;
286 int valuelen;
287 int nmap;
288 int error;
289 int hdrcnt = 0;
290 bool crcs = xfs_sb_version_hascrc(&mp->m_sb);
291 int offset = 0;
292
293 trace_xfs_attr_rmtval_set(args);
294
295 /*
296 * Find a "hole" in the attribute address space large enough for
297 * us to drop the new attribute's value into. Because CRC enable
298 * attributes have headers, we can't just do a straight byte to FSB
299 * conversion. We calculate the worst case block count in this case
300 * and we may not need that many, so we have to handle this when
301 * allocating the blocks below.
302 */
303 if (!crcs)
304 blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
305 else
306 blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
307
308 error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
309 XFS_ATTR_FORK);
310 if (error)
311 return error;
312
313 /* Start with the attribute data. We'll allocate the rest afterwards. */
314 if (crcs)
315 blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
316
317 args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
318 args->rmtblkcnt = blkcnt;
319
320 /*
321 * Roll through the "value", allocating blocks on disk as required.
322 */
323 while (blkcnt > 0) {
324 int committed;
325
326 /*
327 * Allocate a single extent, up to the size of the value.
328 */
329 xfs_bmap_init(args->flist, args->firstblock);
330 nmap = 1;
331 error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
332 blkcnt,
333 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
334 args->firstblock, args->total, &map, &nmap,
335 args->flist);
336 if (!error) {
337 error = xfs_bmap_finish(&args->trans, args->flist,
338 &committed);
339 }
340 if (error) {
341 ASSERT(committed);
342 args->trans = NULL;
343 xfs_bmap_cancel(args->flist);
344 return(error);
345 }
346
347 /*
348 * bmap_finish() may have committed the last trans and started
349 * a new one. We need the inode to be in all transactions.
350 */
351 if (committed)
352 xfs_trans_ijoin(args->trans, dp, 0);
353
354 ASSERT(nmap == 1);
355 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
356 (map.br_startblock != HOLESTARTBLOCK));
357 lblkno += map.br_blockcount;
358 blkcnt -= map.br_blockcount;
359 hdrcnt++;
360
361 /*
362 * If we have enough blocks for the attribute data, calculate
363 * how many extra blocks we need for headers. We might run
364 * through this multiple times in the case that the additional
365 * headers in the blocks needed for the data fragments spills
366 * into requiring more blocks. e.g. for 512 byte blocks, we'll
367 * spill for another block every 9 headers we require in this
368 * loop.
369 */
370
371 if (crcs && blkcnt == 0) {
372 int total_len;
373
374 total_len = args->valuelen +
375 hdrcnt * sizeof(struct xfs_attr3_rmt_hdr);
376 blkcnt = XFS_B_TO_FSB(mp, total_len);
377 blkcnt -= args->rmtblkcnt;
378 args->rmtblkcnt += blkcnt;
379 }
380
381 /*
382 * Start the next trans in the chain.
383 */
384 error = xfs_trans_roll(&args->trans, dp);
385 if (error)
386 return (error);
387 }
388
389 /*
390 * Roll through the "value", copying the attribute value to the
391 * already-allocated blocks. Blocks are written synchronously
392 * so that we can know they are all on disk before we turn off
393 * the INCOMPLETE flag.
394 */
395 lblkno = args->rmtblkno;
396 valuelen = args->valuelen;
397 while (valuelen > 0) {
398 int byte_cnt;
399 char *buf;
400
401 /*
402 * Try to remember where we decided to put the value.
403 */
404 xfs_bmap_init(args->flist, args->firstblock);
405 nmap = 1;
406 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
407 args->rmtblkcnt, &map, &nmap,
408 XFS_BMAPI_ATTRFORK);
409 if (error)
410 return(error);
411 ASSERT(nmap == 1);
412 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
413 (map.br_startblock != HOLESTARTBLOCK));
414
415 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
416 blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
417
418 bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, 0);
419 if (!bp)
420 return ENOMEM;
421 bp->b_ops = &xfs_attr3_rmt_buf_ops;
422
423 byte_cnt = BBTOB(bp->b_length);
424 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, byte_cnt);
425 if (valuelen < byte_cnt) {
426 byte_cnt = valuelen;
427 }
428
429 buf = bp->b_addr;
430 buf += xfs_attr3_rmt_hdr_set(mp, dp->i_ino, offset,
431 byte_cnt, bp);
432 memcpy(buf, src, byte_cnt);
433
434 if (byte_cnt < BBTOB(bp->b_length))
435 xfs_buf_zero(bp, byte_cnt,
436 BBTOB(bp->b_length) - byte_cnt);
437
438 error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
439 xfs_buf_relse(bp);
440 if (error)
441 return error;
442
443 src += byte_cnt;
444 valuelen -= byte_cnt;
445 offset += byte_cnt;
446 hdrcnt--;
447
448 lblkno += map.br_blockcount;
449 }
450 ASSERT(valuelen == 0);
451 ASSERT(hdrcnt == 0);
452 return 0;
453 }
454
455 /*
456 * Remove the value associated with an attribute by deleting the
457 * out-of-line buffer that it is stored on.
458 */
459 int
460 xfs_attr_rmtval_remove(xfs_da_args_t *args)
461 {
462 xfs_mount_t *mp;
463 xfs_bmbt_irec_t map;
464 xfs_buf_t *bp;
465 xfs_daddr_t dblkno;
466 xfs_dablk_t lblkno;
467 int valuelen, blkcnt, nmap, error, done, committed;
468
469 trace_xfs_attr_rmtval_remove(args);
470
471 mp = args->dp->i_mount;
472
473 /*
474 * Roll through the "value", invalidating the attribute value's
475 * blocks.
476 */
477 lblkno = args->rmtblkno;
478 valuelen = args->rmtblkcnt;
479 while (valuelen > 0) {
480 /*
481 * Try to remember where we decided to put the value.
482 */
483 nmap = 1;
484 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
485 args->rmtblkcnt, &map, &nmap,
486 XFS_BMAPI_ATTRFORK);
487 if (error)
488 return(error);
489 ASSERT(nmap == 1);
490 ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
491 (map.br_startblock != HOLESTARTBLOCK));
492
493 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
494 blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
495
496 /*
497 * If the "remote" value is in the cache, remove it.
498 */
499 bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
500 if (bp) {
501 xfs_buf_stale(bp);
502 xfs_buf_relse(bp);
503 bp = NULL;
504 }
505
506 valuelen -= map.br_blockcount;
507
508 lblkno += map.br_blockcount;
509 }
510
511 /*
512 * Keep de-allocating extents until the remote-value region is gone.
513 */
514 lblkno = args->rmtblkno;
515 blkcnt = args->rmtblkcnt;
516 done = 0;
517 while (!done) {
518 xfs_bmap_init(args->flist, args->firstblock);
519 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
520 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
521 1, args->firstblock, args->flist,
522 &done);
523 if (!error) {
524 error = xfs_bmap_finish(&args->trans, args->flist,
525 &committed);
526 }
527 if (error) {
528 ASSERT(committed);
529 args->trans = NULL;
530 xfs_bmap_cancel(args->flist);
531 return error;
532 }
533
534 /*
535 * bmap_finish() may have committed the last trans and started
536 * a new one. We need the inode to be in all transactions.
537 */
538 if (committed)
539 xfs_trans_ijoin(args->trans, args->dp, 0);
540
541 /*
542 * Close out trans and start the next one in the chain.
543 */
544 error = xfs_trans_roll(&args->trans, args->dp);
545 if (error)
546 return (error);
547 }
548 return(0);
549 }
550