aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr_remote.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr_remote.c')
-rw-r--r--fs/xfs/xfs_attr_remote.c381
1 files changed, 228 insertions, 153 deletions
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index d8bcb2d742d1..ef6b0c124528 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -47,7 +47,7 @@
47 * Each contiguous block has a header, so it is not just a simple attribute 47 * Each contiguous block has a header, so it is not just a simple attribute
48 * length to FSB conversion. 48 * length to FSB conversion.
49 */ 49 */
50static int 50int
51xfs_attr3_rmt_blocks( 51xfs_attr3_rmt_blocks(
52 struct xfs_mount *mp, 52 struct xfs_mount *mp,
53 int attrlen) 53 int attrlen)
@@ -59,12 +59,43 @@ xfs_attr3_rmt_blocks(
59 return XFS_B_TO_FSB(mp, attrlen); 59 return XFS_B_TO_FSB(mp, attrlen);
60} 60}
61 61
62/*
63 * Checking of the remote attribute header is split into two parts. The verifier
64 * does CRC, location and bounds checking, the unpacking function checks the
65 * attribute parameters and owner.
66 */
67static bool
68xfs_attr3_rmt_hdr_ok(
69 struct xfs_mount *mp,
70 void *ptr,
71 xfs_ino_t ino,
72 uint32_t offset,
73 uint32_t size,
74 xfs_daddr_t bno)
75{
76 struct xfs_attr3_rmt_hdr *rmt = ptr;
77
78 if (bno != be64_to_cpu(rmt->rm_blkno))
79 return false;
80 if (offset != be32_to_cpu(rmt->rm_offset))
81 return false;
82 if (size != be32_to_cpu(rmt->rm_bytes))
83 return false;
84 if (ino != be64_to_cpu(rmt->rm_owner))
85 return false;
86
87 /* ok */
88 return true;
89}
90
62static bool 91static bool
63xfs_attr3_rmt_verify( 92xfs_attr3_rmt_verify(
64 struct xfs_buf *bp) 93 struct xfs_mount *mp,
94 void *ptr,
95 int fsbsize,
96 xfs_daddr_t bno)
65{ 97{
66 struct xfs_mount *mp = bp->b_target->bt_mount; 98 struct xfs_attr3_rmt_hdr *rmt = ptr;
67 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
68 99
69 if (!xfs_sb_version_hascrc(&mp->m_sb)) 100 if (!xfs_sb_version_hascrc(&mp->m_sb))
70 return false; 101 return false;
@@ -72,7 +103,9 @@ xfs_attr3_rmt_verify(
72 return false; 103 return false;
73 if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid)) 104 if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid))
74 return false; 105 return false;
75 if (bp->b_bn != be64_to_cpu(rmt->rm_blkno)) 106 if (be64_to_cpu(rmt->rm_blkno) != bno)
107 return false;
108 if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
76 return false; 109 return false;
77 if (be32_to_cpu(rmt->rm_offset) + 110 if (be32_to_cpu(rmt->rm_offset) +
78 be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX) 111 be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
@@ -88,17 +121,40 @@ xfs_attr3_rmt_read_verify(
88 struct xfs_buf *bp) 121 struct xfs_buf *bp)
89{ 122{
90 struct xfs_mount *mp = bp->b_target->bt_mount; 123 struct xfs_mount *mp = bp->b_target->bt_mount;
124 char *ptr;
125 int len;
126 bool corrupt = false;
127 xfs_daddr_t bno;
91 128
92 /* no verification of non-crc buffers */ 129 /* no verification of non-crc buffers */
93 if (!xfs_sb_version_hascrc(&mp->m_sb)) 130 if (!xfs_sb_version_hascrc(&mp->m_sb))
94 return; 131 return;
95 132
96 if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), 133 ptr = bp->b_addr;
97 XFS_ATTR3_RMT_CRC_OFF) || 134 bno = bp->b_bn;
98 !xfs_attr3_rmt_verify(bp)) { 135 len = BBTOB(bp->b_length);
136 ASSERT(len >= XFS_LBSIZE(mp));
137
138 while (len > 0) {
139 if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
140 XFS_ATTR3_RMT_CRC_OFF)) {
141 corrupt = true;
142 break;
143 }
144 if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
145 corrupt = true;
146 break;
147 }
148 len -= XFS_LBSIZE(mp);
149 ptr += XFS_LBSIZE(mp);
150 bno += mp->m_bsize;
151 }
152
153 if (corrupt) {
99 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); 154 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
100 xfs_buf_ioerror(bp, EFSCORRUPTED); 155 xfs_buf_ioerror(bp, EFSCORRUPTED);
101 } 156 } else
157 ASSERT(len == 0);
102} 158}
103 159
104static void 160static void
@@ -107,23 +163,39 @@ xfs_attr3_rmt_write_verify(
107{ 163{
108 struct xfs_mount *mp = bp->b_target->bt_mount; 164 struct xfs_mount *mp = bp->b_target->bt_mount;
109 struct xfs_buf_log_item *bip = bp->b_fspriv; 165 struct xfs_buf_log_item *bip = bp->b_fspriv;
166 char *ptr;
167 int len;
168 xfs_daddr_t bno;
110 169
111 /* no verification of non-crc buffers */ 170 /* no verification of non-crc buffers */
112 if (!xfs_sb_version_hascrc(&mp->m_sb)) 171 if (!xfs_sb_version_hascrc(&mp->m_sb))
113 return; 172 return;
114 173
115 if (!xfs_attr3_rmt_verify(bp)) { 174 ptr = bp->b_addr;
116 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); 175 bno = bp->b_bn;
117 xfs_buf_ioerror(bp, EFSCORRUPTED); 176 len = BBTOB(bp->b_length);
118 return; 177 ASSERT(len >= XFS_LBSIZE(mp));
119 } 178
179 while (len > 0) {
180 if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
181 XFS_CORRUPTION_ERROR(__func__,
182 XFS_ERRLEVEL_LOW, mp, bp->b_addr);
183 xfs_buf_ioerror(bp, EFSCORRUPTED);
184 return;
185 }
186 if (bip) {
187 struct xfs_attr3_rmt_hdr *rmt;
120 188
121 if (bip) { 189 rmt = (struct xfs_attr3_rmt_hdr *)ptr;
122 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; 190 rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
123 rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn); 191 }
192 xfs_update_cksum(ptr, XFS_LBSIZE(mp), XFS_ATTR3_RMT_CRC_OFF);
193
194 len -= XFS_LBSIZE(mp);
195 ptr += XFS_LBSIZE(mp);
196 bno += mp->m_bsize;
124 } 197 }
125 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), 198 ASSERT(len == 0);
126 XFS_ATTR3_RMT_CRC_OFF);
127} 199}
128 200
129const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = { 201const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
@@ -131,15 +203,16 @@ const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
131 .verify_write = xfs_attr3_rmt_write_verify, 203 .verify_write = xfs_attr3_rmt_write_verify,
132}; 204};
133 205
134static int 206STATIC int
135xfs_attr3_rmt_hdr_set( 207xfs_attr3_rmt_hdr_set(
136 struct xfs_mount *mp, 208 struct xfs_mount *mp,
209 void *ptr,
137 xfs_ino_t ino, 210 xfs_ino_t ino,
138 uint32_t offset, 211 uint32_t offset,
139 uint32_t size, 212 uint32_t size,
140 struct xfs_buf *bp) 213 xfs_daddr_t bno)
141{ 214{
142 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; 215 struct xfs_attr3_rmt_hdr *rmt = ptr;
143 216
144 if (!xfs_sb_version_hascrc(&mp->m_sb)) 217 if (!xfs_sb_version_hascrc(&mp->m_sb))
145 return 0; 218 return 0;
@@ -149,36 +222,107 @@ xfs_attr3_rmt_hdr_set(
149 rmt->rm_bytes = cpu_to_be32(size); 222 rmt->rm_bytes = cpu_to_be32(size);
150 uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid); 223 uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid);
151 rmt->rm_owner = cpu_to_be64(ino); 224 rmt->rm_owner = cpu_to_be64(ino);
152 rmt->rm_blkno = cpu_to_be64(bp->b_bn); 225 rmt->rm_blkno = cpu_to_be64(bno);
153 bp->b_ops = &xfs_attr3_rmt_buf_ops;
154 226
155 return sizeof(struct xfs_attr3_rmt_hdr); 227 return sizeof(struct xfs_attr3_rmt_hdr);
156} 228}
157 229
158/* 230/*
159 * Checking of the remote attribute header is split into two parts. the verifier 231 * Helper functions to copy attribute data in and out of the one disk extents
160 * does CRC, location and bounds checking, the unpacking function checks the
161 * attribute parameters and owner.
162 */ 232 */
163static bool 233STATIC int
164xfs_attr3_rmt_hdr_ok( 234xfs_attr_rmtval_copyout(
165 struct xfs_mount *mp, 235 struct xfs_mount *mp,
166 xfs_ino_t ino, 236 struct xfs_buf *bp,
167 uint32_t offset, 237 xfs_ino_t ino,
168 uint32_t size, 238 int *offset,
169 struct xfs_buf *bp) 239 int *valuelen,
240 char **dst)
170{ 241{
171 struct xfs_attr3_rmt_hdr *rmt = bp->b_addr; 242 char *src = bp->b_addr;
243 xfs_daddr_t bno = bp->b_bn;
244 int len = BBTOB(bp->b_length);
172 245
173 if (offset != be32_to_cpu(rmt->rm_offset)) 246 ASSERT(len >= XFS_LBSIZE(mp));
174 return false;
175 if (size != be32_to_cpu(rmt->rm_bytes))
176 return false;
177 if (ino != be64_to_cpu(rmt->rm_owner))
178 return false;
179 247
180 /* ok */ 248 while (len > 0 && *valuelen > 0) {
181 return true; 249 int hdr_size = 0;
250 int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
251
252 byte_cnt = min_t(int, *valuelen, byte_cnt);
253
254 if (xfs_sb_version_hascrc(&mp->m_sb)) {
255 if (!xfs_attr3_rmt_hdr_ok(mp, src, ino, *offset,
256 byte_cnt, bno)) {
257 xfs_alert(mp,
258"remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
259 bno, *offset, byte_cnt, ino);
260 return EFSCORRUPTED;
261 }
262 hdr_size = sizeof(struct xfs_attr3_rmt_hdr);
263 }
264
265 memcpy(*dst, src + hdr_size, byte_cnt);
266
267 /* roll buffer forwards */
268 len -= XFS_LBSIZE(mp);
269 src += XFS_LBSIZE(mp);
270 bno += mp->m_bsize;
271
272 /* roll attribute data forwards */
273 *valuelen -= byte_cnt;
274 *dst += byte_cnt;
275 *offset += byte_cnt;
276 }
277 return 0;
278}
279
280STATIC void
281xfs_attr_rmtval_copyin(
282 struct xfs_mount *mp,
283 struct xfs_buf *bp,
284 xfs_ino_t ino,
285 int *offset,
286 int *valuelen,
287 char **src)
288{
289 char *dst = bp->b_addr;
290 xfs_daddr_t bno = bp->b_bn;
291 int len = BBTOB(bp->b_length);
292
293 ASSERT(len >= XFS_LBSIZE(mp));
294
295 while (len > 0 && *valuelen > 0) {
296 int hdr_size;
297 int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
298
299 byte_cnt = min(*valuelen, byte_cnt);
300 hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
301 byte_cnt, bno);
302
303 memcpy(dst + hdr_size, *src, byte_cnt);
304
305 /*
306 * If this is the last block, zero the remainder of it.
307 * Check that we are actually the last block, too.
308 */
309 if (byte_cnt + hdr_size < XFS_LBSIZE(mp)) {
310 ASSERT(*valuelen - byte_cnt == 0);
311 ASSERT(len == XFS_LBSIZE(mp));
312 memset(dst + hdr_size + byte_cnt, 0,
313 XFS_LBSIZE(mp) - hdr_size - byte_cnt);
314 }
315
316 /* roll buffer forwards */
317 len -= XFS_LBSIZE(mp);
318 dst += XFS_LBSIZE(mp);
319 bno += mp->m_bsize;
320
321 /* roll attribute data forwards */
322 *valuelen -= byte_cnt;
323 *src += byte_cnt;
324 *offset += byte_cnt;
325 }
182} 326}
183 327
184/* 328/*
@@ -192,13 +336,12 @@ xfs_attr_rmtval_get(
192 struct xfs_bmbt_irec map[ATTR_RMTVALUE_MAPSIZE]; 336 struct xfs_bmbt_irec map[ATTR_RMTVALUE_MAPSIZE];
193 struct xfs_mount *mp = args->dp->i_mount; 337 struct xfs_mount *mp = args->dp->i_mount;
194 struct xfs_buf *bp; 338 struct xfs_buf *bp;
195 xfs_daddr_t dblkno;
196 xfs_dablk_t lblkno = args->rmtblkno; 339 xfs_dablk_t lblkno = args->rmtblkno;
197 void *dst = args->value; 340 char *dst = args->value;
198 int valuelen = args->valuelen; 341 int valuelen = args->valuelen;
199 int nmap; 342 int nmap;
200 int error; 343 int error;
201 int blkcnt; 344 int blkcnt = args->rmtblkcnt;
202 int i; 345 int i;
203 int offset = 0; 346 int offset = 0;
204 347
@@ -208,7 +351,6 @@ xfs_attr_rmtval_get(
208 351
209 while (valuelen > 0) { 352 while (valuelen > 0) {
210 nmap = ATTR_RMTVALUE_MAPSIZE; 353 nmap = ATTR_RMTVALUE_MAPSIZE;
211 blkcnt = xfs_attr3_rmt_blocks(mp, valuelen);
212 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, 354 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
213 blkcnt, map, &nmap, 355 blkcnt, map, &nmap,
214 XFS_BMAPI_ATTRFORK); 356 XFS_BMAPI_ATTRFORK);
@@ -217,45 +359,29 @@ xfs_attr_rmtval_get(
217 ASSERT(nmap >= 1); 359 ASSERT(nmap >= 1);
218 360
219 for (i = 0; (i < nmap) && (valuelen > 0); i++) { 361 for (i = 0; (i < nmap) && (valuelen > 0); i++) {
220 int byte_cnt; 362 xfs_daddr_t dblkno;
221 char *src; 363 int dblkcnt;
222 364
223 ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) && 365 ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
224 (map[i].br_startblock != HOLESTARTBLOCK)); 366 (map[i].br_startblock != HOLESTARTBLOCK));
225 dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); 367 dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
226 blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); 368 dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
227 error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, 369 error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
228 dblkno, blkcnt, 0, &bp, 370 dblkno, dblkcnt, 0, &bp,
229 &xfs_attr3_rmt_buf_ops); 371 &xfs_attr3_rmt_buf_ops);
230 if (error) 372 if (error)
231 return error; 373 return error;
232 374
233 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, BBTOB(bp->b_length)); 375 error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
234 byte_cnt = min_t(int, valuelen, byte_cnt); 376 &offset, &valuelen,
235 377 &dst);
236 src = bp->b_addr;
237 if (xfs_sb_version_hascrc(&mp->m_sb)) {
238 if (!xfs_attr3_rmt_hdr_ok(mp, args->dp->i_ino,
239 offset, byte_cnt, bp)) {
240 xfs_alert(mp,
241"remote attribute header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
242 offset, byte_cnt, args->dp->i_ino);
243 xfs_buf_relse(bp);
244 return EFSCORRUPTED;
245
246 }
247
248 src += sizeof(struct xfs_attr3_rmt_hdr);
249 }
250
251 memcpy(dst, src, byte_cnt);
252 xfs_buf_relse(bp); 378 xfs_buf_relse(bp);
379 if (error)
380 return error;
253 381
254 offset += byte_cnt; 382 /* roll attribute extent map forwards */
255 dst += byte_cnt;
256 valuelen -= byte_cnt;
257
258 lblkno += map[i].br_blockcount; 383 lblkno += map[i].br_blockcount;
384 blkcnt -= map[i].br_blockcount;
259 } 385 }
260 } 386 }
261 ASSERT(valuelen == 0); 387 ASSERT(valuelen == 0);
@@ -273,17 +399,13 @@ xfs_attr_rmtval_set(
273 struct xfs_inode *dp = args->dp; 399 struct xfs_inode *dp = args->dp;
274 struct xfs_mount *mp = dp->i_mount; 400 struct xfs_mount *mp = dp->i_mount;
275 struct xfs_bmbt_irec map; 401 struct xfs_bmbt_irec map;
276 struct xfs_buf *bp;
277 xfs_daddr_t dblkno;
278 xfs_dablk_t lblkno; 402 xfs_dablk_t lblkno;
279 xfs_fileoff_t lfileoff = 0; 403 xfs_fileoff_t lfileoff = 0;
280 void *src = args->value; 404 char *src = args->value;
281 int blkcnt; 405 int blkcnt;
282 int valuelen; 406 int valuelen;
283 int nmap; 407 int nmap;
284 int error; 408 int error;
285 int hdrcnt = 0;
286 bool crcs = xfs_sb_version_hascrc(&mp->m_sb);
287 int offset = 0; 409 int offset = 0;
288 410
289 trace_xfs_attr_rmtval_set(args); 411 trace_xfs_attr_rmtval_set(args);
@@ -292,21 +414,14 @@ xfs_attr_rmtval_set(
292 * Find a "hole" in the attribute address space large enough for 414 * Find a "hole" in the attribute address space large enough for
293 * us to drop the new attribute's value into. Because CRC enable 415 * us to drop the new attribute's value into. Because CRC enable
294 * attributes have headers, we can't just do a straight byte to FSB 416 * attributes have headers, we can't just do a straight byte to FSB
295 * conversion. We calculate the worst case block count in this case 417 * conversion and have to take the header space into account.
296 * and we may not need that many, so we have to handle this when
297 * allocating the blocks below.
298 */ 418 */
299 blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); 419 blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
300
301 error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, 420 error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
302 XFS_ATTR_FORK); 421 XFS_ATTR_FORK);
303 if (error) 422 if (error)
304 return error; 423 return error;
305 424
306 /* Start with the attribute data. We'll allocate the rest afterwards. */
307 if (crcs)
308 blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
309
310 args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff; 425 args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
311 args->rmtblkcnt = blkcnt; 426 args->rmtblkcnt = blkcnt;
312 427
@@ -349,31 +464,6 @@ xfs_attr_rmtval_set(
349 (map.br_startblock != HOLESTARTBLOCK)); 464 (map.br_startblock != HOLESTARTBLOCK));
350 lblkno += map.br_blockcount; 465 lblkno += map.br_blockcount;
351 blkcnt -= map.br_blockcount; 466 blkcnt -= map.br_blockcount;
352 hdrcnt++;
353
354 /*
355 * If we have enough blocks for the attribute data, calculate
356 * how many extra blocks we need for headers. We might run
357 * through this multiple times in the case that the additional
358 * headers in the blocks needed for the data fragments spills
359 * into requiring more blocks. e.g. for 512 byte blocks, we'll
360 * spill for another block every 9 headers we require in this
361 * loop.
362 *
363 * Note that this can result in contiguous allocation of blocks,
364 * so we don't use all the space we allocate for headers as we
365 * have one less header for each contiguous allocation that
366 * occurs in the map/write loop below.
367 */
368 if (crcs && blkcnt == 0) {
369 int total_len;
370
371 total_len = args->valuelen +
372 hdrcnt * sizeof(struct xfs_attr3_rmt_hdr);
373 blkcnt = XFS_B_TO_FSB(mp, total_len);
374 blkcnt -= args->rmtblkcnt;
375 args->rmtblkcnt += blkcnt;
376 }
377 467
378 /* 468 /*
379 * Start the next trans in the chain. 469 * Start the next trans in the chain.
@@ -390,17 +480,15 @@ xfs_attr_rmtval_set(
390 * the INCOMPLETE flag. 480 * the INCOMPLETE flag.
391 */ 481 */
392 lblkno = args->rmtblkno; 482 lblkno = args->rmtblkno;
393 valuelen = args->valuelen;
394 blkcnt = args->rmtblkcnt; 483 blkcnt = args->rmtblkcnt;
484 valuelen = args->valuelen;
395 while (valuelen > 0) { 485 while (valuelen > 0) {
396 int byte_cnt; 486 struct xfs_buf *bp;
397 int hdr_size; 487 xfs_daddr_t dblkno;
398 int dblkcnt; 488 int dblkcnt;
399 char *buf; 489
490 ASSERT(blkcnt > 0);
400 491
401 /*
402 * Try to remember where we decided to put the value.
403 */
404 xfs_bmap_init(args->flist, args->firstblock); 492 xfs_bmap_init(args->flist, args->firstblock);
405 nmap = 1; 493 nmap = 1;
406 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, 494 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
@@ -419,29 +507,17 @@ xfs_attr_rmtval_set(
419 if (!bp) 507 if (!bp)
420 return ENOMEM; 508 return ENOMEM;
421 bp->b_ops = &xfs_attr3_rmt_buf_ops; 509 bp->b_ops = &xfs_attr3_rmt_buf_ops;
422 buf = bp->b_addr;
423
424 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, BBTOB(bp->b_length));
425 byte_cnt = min_t(int, valuelen, byte_cnt);
426 hdr_size = xfs_attr3_rmt_hdr_set(mp, dp->i_ino, offset,
427 byte_cnt, bp);
428 ASSERT(hdr_size + byte_cnt <= BBTOB(bp->b_length));
429 510
430 memcpy(buf + hdr_size, src, byte_cnt); 511 xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
431 512 &valuelen, &src);
432 if (byte_cnt + hdr_size < BBTOB(bp->b_length))
433 xfs_buf_zero(bp, byte_cnt + hdr_size,
434 BBTOB(bp->b_length) - byte_cnt - hdr_size);
435 513
436 error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ 514 error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
437 xfs_buf_relse(bp); 515 xfs_buf_relse(bp);
438 if (error) 516 if (error)
439 return error; 517 return error;
440 518
441 src += byte_cnt;
442 valuelen -= byte_cnt;
443 offset += byte_cnt;
444 519
520 /* roll attribute extent map forwards */
445 lblkno += map.br_blockcount; 521 lblkno += map.br_blockcount;
446 blkcnt -= map.br_blockcount; 522 blkcnt -= map.br_blockcount;
447 } 523 }
@@ -454,19 +530,17 @@ xfs_attr_rmtval_set(
454 * out-of-line buffer that it is stored on. 530 * out-of-line buffer that it is stored on.
455 */ 531 */
456int 532int
457xfs_attr_rmtval_remove(xfs_da_args_t *args) 533xfs_attr_rmtval_remove(
534 struct xfs_da_args *args)
458{ 535{
459 xfs_mount_t *mp; 536 struct xfs_mount *mp = args->dp->i_mount;
460 xfs_bmbt_irec_t map; 537 xfs_dablk_t lblkno;
461 xfs_buf_t *bp; 538 int blkcnt;
462 xfs_daddr_t dblkno; 539 int error;
463 xfs_dablk_t lblkno; 540 int done;
464 int valuelen, blkcnt, nmap, error, done, committed;
465 541
466 trace_xfs_attr_rmtval_remove(args); 542 trace_xfs_attr_rmtval_remove(args);
467 543
468 mp = args->dp->i_mount;
469
470 /* 544 /*
471 * Roll through the "value", invalidating the attribute value's blocks. 545 * Roll through the "value", invalidating the attribute value's blocks.
472 * Note that args->rmtblkcnt is the minimum number of data blocks we'll 546 * Note that args->rmtblkcnt is the minimum number of data blocks we'll
@@ -476,10 +550,13 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
476 * lookups. 550 * lookups.
477 */ 551 */
478 lblkno = args->rmtblkno; 552 lblkno = args->rmtblkno;
479 valuelen = args->valuelen; 553 blkcnt = args->rmtblkcnt;
480 blkcnt = xfs_attr3_rmt_blocks(mp, valuelen); 554 while (blkcnt > 0) {
481 while (valuelen > 0) { 555 struct xfs_bmbt_irec map;
482 int dblkcnt; 556 struct xfs_buf *bp;
557 xfs_daddr_t dblkno;
558 int dblkcnt;
559 int nmap;
483 560
484 /* 561 /*
485 * Try to remember where we decided to put the value. 562 * Try to remember where we decided to put the value.
@@ -506,21 +583,19 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
506 bp = NULL; 583 bp = NULL;
507 } 584 }
508 585
509 valuelen -= XFS_ATTR3_RMT_BUF_SPACE(mp,
510 XFS_FSB_TO_B(mp, map.br_blockcount));
511
512 lblkno += map.br_blockcount; 586 lblkno += map.br_blockcount;
513 blkcnt -= map.br_blockcount; 587 blkcnt -= map.br_blockcount;
514 blkcnt = max(blkcnt, xfs_attr3_rmt_blocks(mp, valuelen));
515 } 588 }
516 589
517 /* 590 /*
518 * Keep de-allocating extents until the remote-value region is gone. 591 * Keep de-allocating extents until the remote-value region is gone.
519 */ 592 */
520 blkcnt = lblkno - args->rmtblkno;
521 lblkno = args->rmtblkno; 593 lblkno = args->rmtblkno;
594 blkcnt = args->rmtblkcnt;
522 done = 0; 595 done = 0;
523 while (!done) { 596 while (!done) {
597 int committed;
598
524 xfs_bmap_init(args->flist, args->firstblock); 599 xfs_bmap_init(args->flist, args->firstblock);
525 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, 600 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
526 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 601 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,