aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_itable.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_itable.c')
-rw-r--r--fs/xfs/xfs_itable.c102
1 files changed, 54 insertions, 48 deletions
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index cf6754a3c5b3..e19d0a8d5618 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -69,7 +69,7 @@ xfs_bulkstat_one_iget(
69 } 69 }
70 70
71 ASSERT(ip != NULL); 71 ASSERT(ip != NULL);
72 ASSERT(ip->i_blkno != (xfs_daddr_t)0); 72 ASSERT(ip->i_imap.im_blkno != 0);
73 73
74 dic = &ip->i_d; 74 dic = &ip->i_d;
75 75
@@ -125,13 +125,9 @@ STATIC void
125xfs_bulkstat_one_dinode( 125xfs_bulkstat_one_dinode(
126 xfs_mount_t *mp, /* mount point for filesystem */ 126 xfs_mount_t *mp, /* mount point for filesystem */
127 xfs_ino_t ino, /* inode number to get data for */ 127 xfs_ino_t ino, /* inode number to get data for */
128 xfs_dinode_t *dip, /* dinode inode pointer */ 128 xfs_dinode_t *dic, /* dinode inode pointer */
129 xfs_bstat_t *buf) /* return buffer */ 129 xfs_bstat_t *buf) /* return buffer */
130{ 130{
131 xfs_dinode_core_t *dic; /* dinode core info pointer */
132
133 dic = &dip->di_core;
134
135 /* 131 /*
136 * The inode format changed when we moved the link count and 132 * The inode format changed when we moved the link count and
137 * made it 32 bits long. If this is an old format inode, 133 * made it 32 bits long. If this is an old format inode,
@@ -143,7 +139,7 @@ xfs_bulkstat_one_dinode(
143 * the new format. We don't change the version number so that we 139 * the new format. We don't change the version number so that we
144 * can distinguish this from a real new format inode. 140 * can distinguish this from a real new format inode.
145 */ 141 */
146 if (dic->di_version == XFS_DINODE_VERSION_1) { 142 if (dic->di_version == 1) {
147 buf->bs_nlink = be16_to_cpu(dic->di_onlink); 143 buf->bs_nlink = be16_to_cpu(dic->di_onlink);
148 buf->bs_projid = 0; 144 buf->bs_projid = 0;
149 } else { 145 } else {
@@ -162,7 +158,7 @@ xfs_bulkstat_one_dinode(
162 buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec); 158 buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
163 buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec); 159 buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
164 buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec); 160 buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
165 buf->bs_xflags = xfs_dic2xflags(dip); 161 buf->bs_xflags = xfs_dic2xflags(dic);
166 buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog; 162 buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
167 buf->bs_extents = be32_to_cpu(dic->di_nextents); 163 buf->bs_extents = be32_to_cpu(dic->di_nextents);
168 buf->bs_gen = be32_to_cpu(dic->di_gen); 164 buf->bs_gen = be32_to_cpu(dic->di_gen);
@@ -173,7 +169,7 @@ xfs_bulkstat_one_dinode(
173 169
174 switch (dic->di_format) { 170 switch (dic->di_format) {
175 case XFS_DINODE_FMT_DEV: 171 case XFS_DINODE_FMT_DEV:
176 buf->bs_rdev = be32_to_cpu(dip->di_u.di_dev); 172 buf->bs_rdev = xfs_dinode_get_rdev(dic);
177 buf->bs_blksize = BLKDEV_IOSIZE; 173 buf->bs_blksize = BLKDEV_IOSIZE;
178 buf->bs_blocks = 0; 174 buf->bs_blocks = 0;
179 break; 175 break;
@@ -192,27 +188,34 @@ xfs_bulkstat_one_dinode(
192 } 188 }
193} 189}
194 190
191/* Return 0 on success or positive error */
195STATIC int 192STATIC int
196xfs_bulkstat_one_fmt( 193xfs_bulkstat_one_fmt(
197 void __user *ubuffer, 194 void __user *ubuffer,
195 int ubsize,
196 int *ubused,
198 const xfs_bstat_t *buffer) 197 const xfs_bstat_t *buffer)
199{ 198{
199 if (ubsize < sizeof(*buffer))
200 return XFS_ERROR(ENOMEM);
200 if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) 201 if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
201 return -EFAULT; 202 return XFS_ERROR(EFAULT);
202 return sizeof(*buffer); 203 if (ubused)
204 *ubused = sizeof(*buffer);
205 return 0;
203} 206}
204 207
205/* 208/*
206 * Return stat information for one inode. 209 * Return stat information for one inode.
207 * Return 0 if ok, else errno. 210 * Return 0 if ok, else errno.
208 */ 211 */
209int /* error status */ 212int /* error status */
210xfs_bulkstat_one( 213xfs_bulkstat_one_int(
211 xfs_mount_t *mp, /* mount point for filesystem */ 214 xfs_mount_t *mp, /* mount point for filesystem */
212 xfs_ino_t ino, /* inode number to get data for */ 215 xfs_ino_t ino, /* inode number to get data for */
213 void __user *buffer, /* buffer to place output in */ 216 void __user *buffer, /* buffer to place output in */
214 int ubsize, /* size of buffer */ 217 int ubsize, /* size of buffer */
215 void *private_data, /* my private data */ 218 bulkstat_one_fmt_pf formatter, /* formatter, copy to user */
216 xfs_daddr_t bno, /* starting bno of inode cluster */ 219 xfs_daddr_t bno, /* starting bno of inode cluster */
217 int *ubused, /* bytes used by me */ 220 int *ubused, /* bytes used by me */
218 void *dibuff, /* on-disk inode buffer */ 221 void *dibuff, /* on-disk inode buffer */
@@ -221,15 +224,12 @@ xfs_bulkstat_one(
221 xfs_bstat_t *buf; /* return buffer */ 224 xfs_bstat_t *buf; /* return buffer */
222 int error = 0; /* error value */ 225 int error = 0; /* error value */
223 xfs_dinode_t *dip; /* dinode inode pointer */ 226 xfs_dinode_t *dip; /* dinode inode pointer */
224 bulkstat_one_fmt_pf formatter = private_data ? : xfs_bulkstat_one_fmt;
225 227
226 dip = (xfs_dinode_t *)dibuff; 228 dip = (xfs_dinode_t *)dibuff;
227 *stat = BULKSTAT_RV_NOTHING; 229 *stat = BULKSTAT_RV_NOTHING;
228 230
229 if (!buffer || xfs_internal_inum(mp, ino)) 231 if (!buffer || xfs_internal_inum(mp, ino))
230 return XFS_ERROR(EINVAL); 232 return XFS_ERROR(EINVAL);
231 if (ubsize < sizeof(*buf))
232 return XFS_ERROR(ENOMEM);
233 233
234 buf = kmem_alloc(sizeof(*buf), KM_SLEEP); 234 buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
235 235
@@ -244,21 +244,34 @@ xfs_bulkstat_one(
244 xfs_bulkstat_one_dinode(mp, ino, dip, buf); 244 xfs_bulkstat_one_dinode(mp, ino, dip, buf);
245 } 245 }
246 246
247 error = formatter(buffer, buf); 247 error = formatter(buffer, ubsize, ubused, buf);
248 if (error < 0) { 248 if (error)
249 error = EFAULT;
250 goto out_free; 249 goto out_free;
251 }
252 250
253 *stat = BULKSTAT_RV_DIDONE; 251 *stat = BULKSTAT_RV_DIDONE;
254 if (ubused)
255 *ubused = error;
256 252
257 out_free: 253 out_free:
258 kmem_free(buf); 254 kmem_free(buf);
259 return error; 255 return error;
260} 256}
261 257
258int
259xfs_bulkstat_one(
260 xfs_mount_t *mp, /* mount point for filesystem */
261 xfs_ino_t ino, /* inode number to get data for */
262 void __user *buffer, /* buffer to place output in */
263 int ubsize, /* size of buffer */
264 void *private_data, /* my private data */
265 xfs_daddr_t bno, /* starting bno of inode cluster */
266 int *ubused, /* bytes used by me */
267 void *dibuff, /* on-disk inode buffer */
268 int *stat) /* BULKSTAT_RV_... */
269{
270 return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
271 xfs_bulkstat_one_fmt, bno,
272 ubused, dibuff, stat);
273}
274
262/* 275/*
263 * Test to see whether we can use the ondisk inode directly, based 276 * Test to see whether we can use the ondisk inode directly, based
264 * on the given bulkstat flags, filling in dipp accordingly. 277 * on the given bulkstat flags, filling in dipp accordingly.
@@ -287,19 +300,19 @@ xfs_bulkstat_use_dinode(
287 * to disk yet. This is a temporary hack that would require a proper 300 * to disk yet. This is a temporary hack that would require a proper
288 * fix in the future. 301 * fix in the future.
289 */ 302 */
290 if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC || 303 if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
291 !XFS_DINODE_GOOD_VERSION(dip->di_core.di_version) || 304 !XFS_DINODE_GOOD_VERSION(dip->di_version) ||
292 !dip->di_core.di_mode) 305 !dip->di_mode)
293 return 0; 306 return 0;
294 if (flags & BULKSTAT_FG_QUICK) { 307 if (flags & BULKSTAT_FG_QUICK) {
295 *dipp = dip; 308 *dipp = dip;
296 return 1; 309 return 1;
297 } 310 }
298 /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */ 311 /* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
299 aformat = dip->di_core.di_aformat; 312 aformat = dip->di_aformat;
300 if ((XFS_DFORK_Q(dip) == 0) || 313 if ((XFS_DFORK_Q(dip) == 0) ||
301 (aformat == XFS_DINODE_FMT_LOCAL) || 314 (aformat == XFS_DINODE_FMT_LOCAL) ||
302 (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) { 315 (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_anextents)) {
303 *dipp = dip; 316 *dipp = dip;
304 return 1; 317 return 1;
305 } 318 }
@@ -359,7 +372,6 @@ xfs_bulkstat(
359 int ubused; /* bytes used by formatter */ 372 int ubused; /* bytes used by formatter */
360 xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ 373 xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */
361 xfs_dinode_t *dip; /* ptr into bp for specific inode */ 374 xfs_dinode_t *dip; /* ptr into bp for specific inode */
362 xfs_inode_t *ip; /* ptr to in-core inode struct */
363 375
364 /* 376 /*
365 * Get the last inode value, see if there's nothing to do. 377 * Get the last inode value, see if there's nothing to do.
@@ -416,8 +428,7 @@ xfs_bulkstat(
416 /* 428 /*
417 * Allocate and initialize a btree cursor for ialloc btree. 429 * Allocate and initialize a btree cursor for ialloc btree.
418 */ 430 */
419 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO, 431 cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
420 (xfs_inode_t *)0, 0);
421 irbp = irbuf; 432 irbp = irbuf;
422 irbufend = irbuf + nirbuf; 433 irbufend = irbuf + nirbuf;
423 end_of_ag = 0; 434 end_of_ag = 0;
@@ -472,7 +483,7 @@ xfs_bulkstat(
472 * In any case, increment to the next record. 483 * In any case, increment to the next record.
473 */ 484 */
474 if (!error) 485 if (!error)
475 error = xfs_inobt_increment(cur, 0, &tmp); 486 error = xfs_btree_increment(cur, 0, &tmp);
476 } else { 487 } else {
477 /* 488 /*
478 * Start of ag. Lookup the first inode chunk. 489 * Start of ag. Lookup the first inode chunk.
@@ -539,7 +550,7 @@ xfs_bulkstat(
539 * Set agino to after this chunk and bump the cursor. 550 * Set agino to after this chunk and bump the cursor.
540 */ 551 */
541 agino = gino + XFS_INODES_PER_CHUNK; 552 agino = gino + XFS_INODES_PER_CHUNK;
542 error = xfs_inobt_increment(cur, 0, &tmp); 553 error = xfs_btree_increment(cur, 0, &tmp);
543 cond_resched(); 554 cond_resched();
544 } 555 }
545 /* 556 /*
@@ -586,6 +597,8 @@ xfs_bulkstat(
586 597
587 if (flags & (BULKSTAT_FG_QUICK | 598 if (flags & (BULKSTAT_FG_QUICK |
588 BULKSTAT_FG_INLINE)) { 599 BULKSTAT_FG_INLINE)) {
600 int offset;
601
589 ino = XFS_AGINO_TO_INO(mp, agno, 602 ino = XFS_AGINO_TO_INO(mp, agno,
590 agino); 603 agino);
591 bno = XFS_AGB_TO_DADDR(mp, agno, 604 bno = XFS_AGB_TO_DADDR(mp, agno,
@@ -594,21 +607,15 @@ xfs_bulkstat(
594 /* 607 /*
595 * Get the inode cluster buffer 608 * Get the inode cluster buffer
596 */ 609 */
597 ASSERT(xfs_inode_zone != NULL);
598 ip = kmem_zone_zalloc(xfs_inode_zone,
599 KM_SLEEP);
600 ip->i_ino = ino;
601 ip->i_mount = mp;
602 spin_lock_init(&ip->i_flags_lock);
603 if (bp) 610 if (bp)
604 xfs_buf_relse(bp); 611 xfs_buf_relse(bp);
605 error = xfs_itobp(mp, NULL, ip, 612
606 &dip, &bp, bno, 613 error = xfs_inotobp(mp, NULL, ino, &dip,
607 XFS_IMAP_BULKSTAT, 614 &bp, &offset,
608 XFS_BUF_LOCK); 615 XFS_IGET_BULKSTAT);
616
609 if (!error) 617 if (!error)
610 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; 618 clustidx = offset / mp->m_sb.sb_inodesize;
611 kmem_zone_free(xfs_inode_zone, ip);
612 if (XFS_TEST_ERROR(error != 0, 619 if (XFS_TEST_ERROR(error != 0,
613 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, 620 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
614 XFS_RANDOM_BULKSTAT_READ_CHUNK)) { 621 XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
@@ -842,8 +849,7 @@ xfs_inumbers(
842 agino = 0; 849 agino = 0;
843 continue; 850 continue;
844 } 851 }
845 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, 852 cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
846 XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
847 error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp); 853 error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp);
848 if (error) { 854 if (error) {
849 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 855 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
@@ -887,7 +893,7 @@ xfs_inumbers(
887 bufidx = 0; 893 bufidx = 0;
888 } 894 }
889 if (left) { 895 if (left) {
890 error = xfs_inobt_increment(cur, 0, &tmp); 896 error = xfs_btree_increment(cur, 0, &tmp);
891 if (error) { 897 if (error) {
892 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 898 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
893 cur = NULL; 899 cur = NULL;