diff options
| author | Dave Chinner <david@fromorbit.com> | 2014-08-03 23:54:46 -0400 |
|---|---|---|
| committer | Dave Chinner <david@fromorbit.com> | 2014-08-03 23:54:46 -0400 |
| commit | b076d8720d793cde04b75b4941b8774e209649b4 (patch) | |
| tree | 14f0aa5ac5850e2077076062340eb1ef15f7ccf1 | |
| parent | 4d7eece2c0dad832c5f224629eba3cced3f2d6cd (diff) | |
| parent | 1e773c4989d2dfe08332b4c18f7e1d7ad633015c (diff) | |
Merge branch 'xfs-bulkstat-refactor' into for-next
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl32.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.c | 569 | ||||
| -rw-r--r-- | fs/xfs/xfs_itable.h | 23 |
4 files changed, 283 insertions, 315 deletions
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 30983b8ceaa1..494237ed4a65 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -796,8 +796,8 @@ xfs_ioc_bulkstat( | |||
| 796 | error = xfs_inumbers(mp, &inlast, &count, | 796 | error = xfs_inumbers(mp, &inlast, &count, |
| 797 | bulkreq.ubuffer, xfs_inumbers_fmt); | 797 | bulkreq.ubuffer, xfs_inumbers_fmt); |
| 798 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) | 798 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) |
| 799 | error = xfs_bulkstat_single(mp, &inlast, | 799 | error = xfs_bulkstat_one(mp, inlast, bulkreq.ubuffer, |
| 800 | bulkreq.ubuffer, &done); | 800 | sizeof(xfs_bstat_t), NULL, &done); |
| 801 | else /* XFS_IOC_FSBULKSTAT */ | 801 | else /* XFS_IOC_FSBULKSTAT */ |
| 802 | error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one, | 802 | error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one, |
| 803 | sizeof(xfs_bstat_t), bulkreq.ubuffer, | 803 | sizeof(xfs_bstat_t), bulkreq.ubuffer, |
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index e65ea67e3ae3..cf63418bf05f 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c | |||
| @@ -102,7 +102,7 @@ xfs_compat_growfs_rt_copyin( | |||
| 102 | STATIC int | 102 | STATIC int |
| 103 | xfs_inumbers_fmt_compat( | 103 | xfs_inumbers_fmt_compat( |
| 104 | void __user *ubuffer, | 104 | void __user *ubuffer, |
| 105 | const xfs_inogrp_t *buffer, | 105 | const struct xfs_inogrp *buffer, |
| 106 | long count, | 106 | long count, |
| 107 | long *written) | 107 | long *written) |
| 108 | { | 108 | { |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 7e54992bcae9..f71be9c68017 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
| @@ -76,10 +76,8 @@ xfs_bulkstat_one_int( | |||
| 76 | error = xfs_iget(mp, NULL, ino, | 76 | error = xfs_iget(mp, NULL, ino, |
| 77 | (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED), | 77 | (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED), |
| 78 | XFS_ILOCK_SHARED, &ip); | 78 | XFS_ILOCK_SHARED, &ip); |
| 79 | if (error) { | 79 | if (error) |
| 80 | *stat = BULKSTAT_RV_NOTHING; | ||
| 81 | goto out_free; | 80 | goto out_free; |
| 82 | } | ||
| 83 | 81 | ||
| 84 | ASSERT(ip != NULL); | 82 | ASSERT(ip != NULL); |
| 85 | ASSERT(ip->i_imap.im_blkno != 0); | 83 | ASSERT(ip->i_imap.im_blkno != 0); |
| @@ -136,7 +134,6 @@ xfs_bulkstat_one_int( | |||
| 136 | IRELE(ip); | 134 | IRELE(ip); |
| 137 | 135 | ||
| 138 | error = formatter(buffer, ubsize, ubused, buf); | 136 | error = formatter(buffer, ubsize, ubused, buf); |
| 139 | |||
| 140 | if (!error) | 137 | if (!error) |
| 141 | *stat = BULKSTAT_RV_DIDONE; | 138 | *stat = BULKSTAT_RV_DIDONE; |
| 142 | 139 | ||
| @@ -175,9 +172,170 @@ xfs_bulkstat_one( | |||
| 175 | xfs_bulkstat_one_fmt, ubused, stat); | 172 | xfs_bulkstat_one_fmt, ubused, stat); |
| 176 | } | 173 | } |
| 177 | 174 | ||
| 175 | /* | ||
| 176 | * Loop over all clusters in a chunk for a given incore inode allocation btree | ||
| 177 | * record. Do a readahead if there are any allocated inodes in that cluster. | ||
| 178 | */ | ||
| 179 | STATIC void | ||
| 180 | xfs_bulkstat_ichunk_ra( | ||
| 181 | struct xfs_mount *mp, | ||
| 182 | xfs_agnumber_t agno, | ||
| 183 | struct xfs_inobt_rec_incore *irec) | ||
| 184 | { | ||
| 185 | xfs_agblock_t agbno; | ||
| 186 | struct blk_plug plug; | ||
| 187 | int blks_per_cluster; | ||
| 188 | int inodes_per_cluster; | ||
| 189 | int i; /* inode chunk index */ | ||
| 190 | |||
| 191 | agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino); | ||
| 192 | blks_per_cluster = xfs_icluster_size_fsb(mp); | ||
| 193 | inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog; | ||
| 194 | |||
| 195 | blk_start_plug(&plug); | ||
| 196 | for (i = 0; i < XFS_INODES_PER_CHUNK; | ||
| 197 | i += inodes_per_cluster, agbno += blks_per_cluster) { | ||
| 198 | if (xfs_inobt_maskn(i, inodes_per_cluster) & ~irec->ir_free) { | ||
| 199 | xfs_btree_reada_bufs(mp, agno, agbno, blks_per_cluster, | ||
| 200 | &xfs_inode_buf_ops); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | blk_finish_plug(&plug); | ||
| 204 | } | ||
| 205 | |||
| 206 | /* | ||
| 207 | * Lookup the inode chunk that the given inode lives in and then get the record | ||
| 208 | * if we found the chunk. If the inode was not the last in the chunk and there | ||
| 209 | * are some left allocated, update the data for the pointed-to record as well as | ||
| 210 | * return the count of grabbed inodes. | ||
| 211 | */ | ||
| 212 | STATIC int | ||
| 213 | xfs_bulkstat_grab_ichunk( | ||
| 214 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
| 215 | xfs_agino_t agino, /* starting inode of chunk */ | ||
| 216 | int *icount,/* return # of inodes grabbed */ | ||
| 217 | struct xfs_inobt_rec_incore *irec) /* btree record */ | ||
| 218 | { | ||
| 219 | int idx; /* index into inode chunk */ | ||
| 220 | int stat; | ||
| 221 | int error = 0; | ||
| 222 | |||
| 223 | /* Lookup the inode chunk that this inode lives in */ | ||
| 224 | error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &stat); | ||
| 225 | if (error) | ||
| 226 | return error; | ||
| 227 | if (!stat) { | ||
| 228 | *icount = 0; | ||
| 229 | return error; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Get the record, should always work */ | ||
| 233 | error = xfs_inobt_get_rec(cur, irec, &stat); | ||
| 234 | if (error) | ||
| 235 | return error; | ||
| 236 | XFS_WANT_CORRUPTED_RETURN(stat == 1); | ||
| 237 | |||
| 238 | /* Check if the record contains the inode in request */ | ||
| 239 | if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino) | ||
| 240 | return -EINVAL; | ||
| 241 | |||
| 242 | idx = agino - irec->ir_startino + 1; | ||
| 243 | if (idx < XFS_INODES_PER_CHUNK && | ||
| 244 | (xfs_inobt_maskn(idx, XFS_INODES_PER_CHUNK - idx) & ~irec->ir_free)) { | ||
| 245 | int i; | ||
| 246 | |||
| 247 | /* We got a right chunk with some left inodes allocated at it. | ||
| 248 | * Grab the chunk record. Mark all the uninteresting inodes | ||
| 249 | * free -- because they're before our start point. | ||
| 250 | */ | ||
| 251 | for (i = 0; i < idx; i++) { | ||
| 252 | if (XFS_INOBT_MASK(i) & ~irec->ir_free) | ||
| 253 | irec->ir_freecount++; | ||
| 254 | } | ||
| 255 | |||
| 256 | irec->ir_free |= xfs_inobt_maskn(0, idx); | ||
| 257 | *icount = XFS_INODES_PER_CHUNK - irec->ir_freecount; | ||
| 258 | } | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 178 | #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) | 263 | #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) |
| 179 | 264 | ||
| 180 | /* | 265 | /* |
| 266 | * Process inodes in chunk with a pointer to a formatter function | ||
| 267 | * that will iget the inode and fill in the appropriate structure. | ||
| 268 | */ | ||
| 269 | int | ||
| 270 | xfs_bulkstat_ag_ichunk( | ||
| 271 | struct xfs_mount *mp, | ||
| 272 | xfs_agnumber_t agno, | ||
| 273 | struct xfs_inobt_rec_incore *irbp, | ||
| 274 | bulkstat_one_pf formatter, | ||
| 275 | size_t statstruct_size, | ||
| 276 | struct xfs_bulkstat_agichunk *acp) | ||
| 277 | { | ||
| 278 | xfs_ino_t lastino = acp->ac_lastino; | ||
| 279 | char __user **ubufp = acp->ac_ubuffer; | ||
| 280 | int ubleft = acp->ac_ubleft; | ||
| 281 | int ubelem = acp->ac_ubelem; | ||
| 282 | int chunkidx, clustidx; | ||
| 283 | int error = 0; | ||
| 284 | xfs_agino_t agino; | ||
| 285 | |||
| 286 | for (agino = irbp->ir_startino, chunkidx = clustidx = 0; | ||
| 287 | XFS_BULKSTAT_UBLEFT(ubleft) && | ||
| 288 | irbp->ir_freecount < XFS_INODES_PER_CHUNK; | ||
| 289 | chunkidx++, clustidx++, agino++) { | ||
| 290 | int fmterror; /* bulkstat formatter result */ | ||
| 291 | int ubused; | ||
| 292 | xfs_ino_t ino = XFS_AGINO_TO_INO(mp, agno, agino); | ||
| 293 | |||
| 294 | ASSERT(chunkidx < XFS_INODES_PER_CHUNK); | ||
| 295 | |||
| 296 | /* Skip if this inode is free */ | ||
| 297 | if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) { | ||
| 298 | lastino = ino; | ||
| 299 | continue; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* | ||
| 303 | * Count used inodes as free so we can tell when the | ||
| 304 | * chunk is used up. | ||
| 305 | */ | ||
