Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: refactor INUMBERS to use iwalk functions

Now that we have generic functions to walk inode records, refactor the
INUMBERS implementation to use it.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>

+93 -150
+13 -7
fs/xfs/xfs_ioctl.c
··· 724 724 return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat)); 725 725 } 726 726 727 + int 728 + xfs_inumbers_fmt( 729 + struct xfs_ibulk *breq, 730 + const struct xfs_inogrp *igrp) 731 + { 732 + if (copy_to_user(breq->ubuffer, igrp, sizeof(*igrp))) 733 + return -EFAULT; 734 + return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp)); 735 + } 736 + 727 737 STATIC int 728 738 xfs_ioc_bulkstat( 729 739 xfs_mount_t *mp, ··· 784 774 * in filesystem". 785 775 */ 786 776 if (cmd == XFS_IOC_FSINUMBERS) { 787 - int count = breq.icount; 788 - 789 - breq.startino = lastino; 790 - error = xfs_inumbers(mp, &breq.startino, &count, 791 - bulkreq.ubuffer, xfs_inumbers_fmt); 792 - breq.ocount = count; 793 - lastino = breq.startino; 777 + breq.startino = lastino ? lastino + 1 : 0; 778 + error = xfs_inumbers(&breq, xfs_inumbers_fmt); 779 + lastino = breq.startino - 1; 794 780 } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) { 795 781 breq.startino = lastino; 796 782 breq.icount = 1;
+2
fs/xfs/xfs_ioctl.h
··· 79 79 80 80 struct xfs_ibulk; 81 81 struct xfs_bstat; 82 + struct xfs_inogrp; 82 83 83 84 int xfs_bulkstat_one_fmt(struct xfs_ibulk *breq, const struct xfs_bstat *bstat); 85 + int xfs_inumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp); 84 86 85 87 #endif
+13 -22
fs/xfs/xfs_ioctl32.c
··· 81 81 82 82 STATIC int 83 83 xfs_inumbers_fmt_compat( 84 - void __user *ubuffer, 85 - const struct xfs_inogrp *buffer, 86 - long count, 87 - long *written) 84 + struct xfs_ibulk *breq, 85 + const struct xfs_inogrp *igrp) 88 86 { 89 - compat_xfs_inogrp_t __user *p32 = ubuffer; 90 - long i; 87 + struct compat_xfs_inogrp __user *p32 = breq->ubuffer; 91 88 92 - for (i = 0; i < count; i++) { 93 - if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || 94 - put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || 95 - put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) 96 - return -EFAULT; 97 - } 98 - *written = count * sizeof(*p32); 99 - return 0; 89 + if (put_user(igrp->xi_startino, &p32->xi_startino) || 90 + put_user(igrp->xi_alloccount, &p32->xi_alloccount) || 91 + put_user(igrp->xi_allocmask, &p32->xi_allocmask)) 92 + return -EFAULT; 93 + 94 + return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_inogrp)); 100 95 } 101 96 102 97 #else ··· 217 222 * to userpace memory via bulkreq.ubuffer. Normally the compat 218 223 * functions and structure size are the correct ones to use ... 219 224 */ 220 - inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat; 225 + inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat; 221 226 bulkstat_one_fmt_pf bs_one_func = xfs_bulkstat_one_fmt_compat; 222 227 223 228 #ifdef CONFIG_X86_X32 ··· 279 284 * in filesystem". 280 285 */ 281 286 if (cmd == XFS_IOC_FSINUMBERS_32) { 282 - int count = breq.icount; 283 - 284 - breq.startino = lastino; 285 - error = xfs_inumbers(mp, &breq.startino, &count, 286 - bulkreq.ubuffer, inumbers_func); 287 - breq.ocount = count; 288 - lastino = breq.startino; 287 + breq.startino = lastino ? lastino + 1 : 0; 288 + error = xfs_inumbers(&breq, inumbers_func); 289 + lastino = breq.startino - 1; 289 290 } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) { 290 291 breq.startino = lastino; 291 292 breq.icount = 1;
+62 -102
fs/xfs/xfs_itable.c
··· 265 265 return error; 266 266 } 267 267 268 - int 269 - xfs_inumbers_fmt( 270 - void __user *ubuffer, /* buffer to write to */ 271 - const struct xfs_inogrp *buffer, /* buffer to read from */ 272 - long count, /* # of elements to read */ 273 - long *written) /* # of bytes written */ 268 + struct xfs_inumbers_chunk { 269 + inumbers_fmt_pf formatter; 270 + struct xfs_ibulk *breq; 271 + }; 272 + 273 + /* 274 + * INUMBERS 275 + * ======== 276 + * This is how we export inode btree records to userspace, so that XFS tools 277 + * can figure out where inodes are allocated. 278 + */ 279 + 280 + /* 281 + * Format the inode group structure and report it somewhere. 282 + * 283 + * Similar to xfs_bulkstat_one_int, lastino is the inode cursor as we walk 284 + * through the filesystem so we move it forward unless there was a runtime 285 + * error. If the formatter tells us the buffer is now full we also move the 286 + * cursor forward and abort the walk. 287 + */ 288 + STATIC int 289 + xfs_inumbers_walk( 290 + struct xfs_mount *mp, 291 + struct xfs_trans *tp, 292 + xfs_agnumber_t agno, 293 + const struct xfs_inobt_rec_incore *irec, 294 + void *data) 274 295 { 275 - if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer))) 276 - return -EFAULT; 277 - *written = count * sizeof(*buffer); 278 - return 0; 296 + struct xfs_inogrp inogrp = { 297 + .xi_startino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino), 298 + .xi_alloccount = irec->ir_count - irec->ir_freecount, 299 + .xi_allocmask = ~irec->ir_free, 300 + }; 301 + struct xfs_inumbers_chunk *ic = data; 302 + xfs_agino_t agino; 303 + int error; 304 + 305 + error = ic->formatter(ic->breq, &inogrp); 306 + if (error && error != XFS_IBULK_ABORT) 307 + return error; 308 + 309 + agino = irec->ir_startino + XFS_INODES_PER_CHUNK; 310 + ic->breq->startino = XFS_AGINO_TO_INO(mp, agno, agino); 311 + return error; 279 312 } 280 313 281 314 /* 282 315 * Return inode number table for the filesystem. 283 316 */ 284 - int /* error status */ 317 + int 285 318 xfs_inumbers( 286 - struct xfs_mount *mp,/* mount point for filesystem */ 287 - xfs_ino_t *lastino,/* last inode returned */ 288 - int *count,/* size of buffer/count returned */ 289 - void __user *ubuffer,/* buffer with inode descriptions */ 319 + struct xfs_ibulk *breq, 290 320 inumbers_fmt_pf formatter) 291 321 { 292 - xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, *lastino); 293 - xfs_agino_t agino = XFS_INO_TO_AGINO(mp, *lastino); 294 - struct xfs_btree_cur *cur = NULL; 295 - struct xfs_buf *agbp = NULL; 296 - struct xfs_inogrp *buffer; 297 - int bcount; 298 - int left = *count; 299 - int bufidx = 0; 322 + struct xfs_inumbers_chunk ic = { 323 + .formatter = formatter, 324 + .breq = breq, 325 + }; 300 326 int error = 0; 301 327 302 - *count = 0; 303 - if (agno >= mp->m_sb.sb_agcount || 304 - *lastino != XFS_AGINO_TO_INO(mp, agno, agino)) 305 - return error; 328 + if (xfs_bulkstat_already_done(breq->mp, breq->startino)) 329 + return 0; 306 330 307 - bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer))); 308 - buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP); 309 - do { 310 - struct xfs_inobt_rec_incore r; 311 - int stat; 331 + error = xfs_inobt_walk(breq->mp, NULL, breq->startino, 332 + xfs_inumbers_walk, breq->icount, &ic); 312 333 313 - if (!agbp) { 314 - error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); 315 - if (error) 316 - break; 317 - 318 - cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, 319 - XFS_BTNUM_INO); 320 - error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, 321 - &stat); 322 - if (error) 323 - break; 324 - if (!stat) 325 - goto next_ag; 326 - } 327 - 328 - error = xfs_inobt_get_rec(cur, &r, &stat); 329 - if (error) 330 - break; 331 - if (!stat) 332 - goto next_ag; 333 - 334 - agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1; 335 - buffer[bufidx].xi_startino = 336 - XFS_AGINO_TO_INO(mp, agno, r.ir_startino); 337 - buffer[bufidx].xi_alloccount = r.ir_count - r.ir_freecount; 338 - buffer[bufidx].xi_allocmask = ~r.ir_free; 339 - if (++bufidx == bcount) { 340 - long written; 341 - 342 - error = formatter(ubuffer, buffer, bufidx, &written); 343 - if (error) 344 - break; 345 - ubuffer += written; 346 - *count += bufidx; 347 - bufidx = 0; 348 - } 349 - if (!--left) 350 - break; 351 - 352 - error = xfs_btree_increment(cur, 0, &stat); 353 - if (error) 354 - break; 355 - if (stat) 356 - continue; 357 - 358 - next_ag: 359 - xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 360 - cur = NULL; 361 - xfs_buf_relse(agbp); 362 - agbp = NULL; 363 - agino = 0; 364 - agno++; 365 - } while (agno < mp->m_sb.sb_agcount); 366 - 367 - if (!error) { 368 - if (bufidx) { 369 - long written; 370 - 371 - error = formatter(ubuffer, buffer, bufidx, &written); 372 - if (!error) 373 - *count += bufidx; 374 - } 375 - *lastino = XFS_AGINO_TO_INO(mp, agno, agino); 376 - } 377 - 378 - kmem_free(buffer); 379 - if (cur) 380 - xfs_btree_del_cursor(cur, error); 381 - if (agbp) 382 - xfs_buf_relse(agbp); 334 + /* 335 + * We found some inode groups, so clear the error status and return 336 + * them. The lastino pointer will point directly at the inode that 337 + * triggered any error that occurred, so on the next call the error 338 + * will be triggered again and propagated to userspace as there will be 339 + * no formatted inode groups in the buffer. 340 + */ 341 + if (breq->ocount > 0) 342 + error = 0; 383 343 384 344 return error; 385 345 }
+3 -19
fs/xfs/xfs_itable.h
··· 43 43 int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter); 44 44 int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter); 45 45 46 - typedef int (*inumbers_fmt_pf)( 47 - void __user *ubuffer, /* buffer to write to */ 48 - const xfs_inogrp_t *buffer, /* buffer to read from */ 49 - long count, /* # of elements to read */ 50 - long *written); /* # of bytes written */ 46 + typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq, 47 + const struct xfs_inogrp *igrp); 51 48 52 - int 53 - xfs_inumbers_fmt( 54 - void __user *ubuffer, /* buffer to write to */ 55 - const xfs_inogrp_t *buffer, /* buffer to read from */ 56 - long count, /* # of elements to read */ 57 - long *written); /* # of bytes written */ 58 - 59 - int /* error status */ 60 - xfs_inumbers( 61 - xfs_mount_t *mp, /* mount point for filesystem */ 62 - xfs_ino_t *last, /* last inode returned */ 63 - int *count, /* size of buffer/count returned */ 64 - void __user *buffer, /* buffer with inode info */ 65 - inumbers_fmt_pf formatter); 49 + int xfs_inumbers(struct xfs_ibulk *breq, inumbers_fmt_pf formatter); 66 50 67 51 #endif /* __XFS_ITABLE_H__ */