X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fxfs%2Fxfs_itable.c;h=36dc09c8c1aa1254afa2a07629bb163d7afb23c0;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=419fcf82a00e225819abcac3fb3f7db273ebf476;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 419fcf82a..36dc09c8c 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -55,16 +55,20 @@ #include "xfs_itable.h" #include "xfs_error.h" +#ifndef HAVE_USERACC +#define useracc(ubuffer, size, flags, foo) (0) +#define unuseracc(ubuffer, size, flags) +#endif + /* * Return stat information for one inode. * Return 0 if ok, else errno. */ -int /* error status */ +int /* error status */ xfs_bulkstat_one( xfs_mount_t *mp, /* mount point for filesystem */ - xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t ino, /* inode number to get data for */ - void *buffer, /* buffer to place output in */ + void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ void *private_data, /* my private data */ xfs_daddr_t bno, /* starting bno of inode cluster */ @@ -78,12 +82,10 @@ xfs_bulkstat_one( xfs_dinode_core_t *dic; /* dinode core info pointer */ xfs_inode_t *ip = NULL; /* incore inode pointer */ xfs_arch_t arch; /* these are set according to */ - __uint16_t di_flags; /* temp */ - buf = (xfs_bstat_t *)buffer; dip = (xfs_dinode_t *)dibuff; - if (! buf || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || + if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) { *stat = BULKSTAT_RV_NOTHING; @@ -94,11 +96,13 @@ xfs_bulkstat_one( return XFS_ERROR(ENOMEM); } + buf = kmem_alloc(sizeof(*buf), KM_SLEEP); + if (dip == NULL) { /* We're not being passed a pointer to a dinode. This happens * if BULKSTAT_FG_IGET is selected. Do the iget. */ - error = xfs_iget(mp, tp, ino, XFS_ILOCK_SHARED, &ip, bno); + error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, bno); if (error) { *stat = BULKSTAT_RV_NOTHING; return error; @@ -108,6 +112,7 @@ xfs_bulkstat_one( if (ip->i_d.di_mode == 0) { xfs_iput_new(ip, XFS_ILOCK_SHARED); *stat = BULKSTAT_RV_NOTHING; + kmem_free(buf, sizeof(*buf)); return XFS_ERROR(ENOENT); } dic = &ip->i_d; @@ -160,29 +165,7 @@ xfs_bulkstat_one( buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, arch); buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, arch); buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, arch); - /* - * convert di_flags to bs_xflags. - */ - di_flags = INT_GET(dic->di_flags, arch); - - buf->bs_xflags = - ((di_flags & XFS_DIFLAG_REALTIME) ? - XFS_XFLAG_REALTIME : 0) | - ((di_flags & XFS_DIFLAG_PREALLOC) ? - XFS_XFLAG_PREALLOC : 0) | - ((di_flags & XFS_DIFLAG_IMMUTABLE) ? - XFS_XFLAG_IMMUTABLE : 0) | - ((di_flags & XFS_DIFLAG_APPEND) ? - XFS_XFLAG_APPEND : 0) | - ((di_flags & XFS_DIFLAG_SYNC) ? - XFS_XFLAG_SYNC : 0) | - ((di_flags & XFS_DIFLAG_NOATIME) ? - XFS_XFLAG_NOATIME : 0) | - ((di_flags & XFS_DIFLAG_NODUMP) ? - XFS_XFLAG_NODUMP : 0) | - (XFS_CFORK_Q_ARCH(dic, arch) ? - XFS_XFLAG_HASATTR : 0); - + buf->bs_xflags = xfs_dic2xflags(dic, arch); buf->bs_extsize = INT_GET(dic->di_extsize, arch) << mp->m_sb.sb_blocklog; buf->bs_extents = INT_GET(dic->di_nextents, arch); buf->bs_gen = INT_GET(dic->di_gen, arch); @@ -224,6 +207,13 @@ xfs_bulkstat_one( xfs_iput(ip, XFS_ILOCK_SHARED); } + if (copy_to_user(buffer, buf, sizeof(*buf))) { + kmem_free(buf, sizeof(*buf)); + *stat = BULKSTAT_RV_NOTHING; + return EFAULT; + } + + kmem_free(buf, sizeof(*buf)); *stat = BULKSTAT_RV_DIDONE; if (ubused) *ubused = sizeof(*buf); @@ -236,13 +226,12 @@ xfs_bulkstat_one( int /* error status */ xfs_bulkstat( xfs_mount_t *mp, /* mount point for filesystem */ - xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t *lastinop, /* last inode returned */ int *ubcountp, /* size of buffer/count returned */ bulkstat_one_pf formatter, /* func that'd fill a single buf */ void *private_data,/* private data for formatter */ size_t statstruct_size, /* sizeof struct filling */ - xfs_caddr_t ubuffer, /* buffer with inode stats */ + char __user *ubuffer, /* buffer with inode stats */ int flags, /* defined in xfs_itable.h */ int *done) /* 1 if there're more stats to get */ { @@ -276,7 +265,7 @@ xfs_bulkstat( int tmp; /* result value from btree calls */ int ubcount; /* size of user's buffer */ int ubleft; /* bytes left in user's buffer */ - xfs_caddr_t ubufp; /* current pointer into user's buffer */ + char __user *ubufp; /* pointer into user's buffer */ int ubelem; /* spaces used in user's buffer */ int ubused; /* bytes used by formatter */ xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ @@ -311,13 +300,11 @@ xfs_bulkstat( * Lock down the user's buffer. If a buffer was not sent, as in the case * disk quota code calls here, we skip this. */ -#if defined(HAVE_USERACC) if (ubuffer && (error = useracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS), NULL))) { return error; } -#endif /* * Allocate a page-sized buffer for inode btree records. * We could try allocating something smaller, but for normal @@ -333,7 +320,7 @@ xfs_bulkstat( while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) { bp = NULL; down_read(&mp->m_peraglock); - error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); + error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); up_read(&mp->m_peraglock); if (error) { /* @@ -347,7 +334,7 @@ xfs_bulkstat( /* * Allocate and initialize a btree cursor for ialloc btree. */ - cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO, + cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO, (xfs_inode_t *)0, 0); irbp = irbuf; irbufend = irbuf + nirbuf; @@ -461,7 +448,7 @@ xfs_bulkstat( * when calling iget. */ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); - xfs_trans_brelse(tp, agbp); + xfs_buf_relse(agbp); /* * Now format all the good inodes into the user's buffer. */ @@ -534,8 +521,8 @@ xfs_bulkstat( ip->i_ino = ino; ip->i_mount = mp; if (bp) - xfs_trans_brelse(tp, bp); - error = xfs_itobp(mp, tp, ip, + xfs_buf_relse(bp); + error = xfs_itobp(mp, NULL, ip, &dip, &bp, bno); if (!error) clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; @@ -580,7 +567,7 @@ xfs_bulkstat( * in xfs_qm_quotacheck. */ ubused = statstruct_size; - error = formatter(mp, tp, ino, ubufp, + error = formatter(mp, ino, ubufp, ubleft, private_data, bno, &ubused, dip, &fmterror); if (fmterror == BULKSTAT_RV_NOTHING) { @@ -603,7 +590,7 @@ xfs_bulkstat( } if (bp) - xfs_trans_brelse(tp, bp); + xfs_buf_relse(bp); /* * Set up for the next loop iteration. @@ -621,10 +608,8 @@ xfs_bulkstat( * Done, we're either out of filesystem or space to put the data. */ kmem_free(irbuf, NBPC); -#if defined(HAVE_USERACC) if (ubuffer) unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS)); -#endif *ubcountp = ubelem; if (agno >= mp->m_sb.sb_agcount) { /* @@ -648,10 +633,9 @@ int /* error status */ xfs_bulkstat_single( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastinop, /* inode to return */ - xfs_caddr_t buffer, /* buffer with inode stats */ + char __user *buffer, /* buffer with inode stats */ int *done) /* 1 if there're more stats to get */ { - xfs_bstat_t bstat; /* one bulkstat result structure */ int count; /* count value for bulkstat call */ int error; /* return value */ xfs_ino_t ino; /* filesystem inode number */ @@ -667,7 +651,7 @@ xfs_bulkstat_single( */ ino = (xfs_ino_t)*lastinop; - error = xfs_bulkstat_one(mp, NULL, ino, &bstat, sizeof(bstat), + error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), NULL, 0, NULL, NULL, &res); if (error) { /* @@ -676,9 +660,9 @@ xfs_bulkstat_single( */ (*lastinop)--; count = 1; - if (xfs_bulkstat(mp, NULL, lastinop, &count, xfs_bulkstat_one, - NULL, - sizeof(bstat), buffer, BULKSTAT_FG_IGET, done)) + if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one, + NULL, sizeof(xfs_bstat_t), buffer, + BULKSTAT_FG_IGET, done)) return error; if (count == 0 || (xfs_ino_t)*lastinop != ino) return error == EFSCORRUPTED ? @@ -687,8 +671,6 @@ xfs_bulkstat_single( return 0; } *done = 0; - if (copy_to_user(buffer, &bstat, sizeof(bstat))) - return XFS_ERROR(EFAULT); return 0; } @@ -698,10 +680,9 @@ xfs_bulkstat_single( int /* error status */ xfs_inumbers( xfs_mount_t *mp, /* mount point for filesystem */ - xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t *lastino, /* last inode returned */ int *count, /* size of buffer/count returned */ - xfs_caddr_t ubuffer) /* buffer with inode descriptions */ + xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */ { xfs_buf_t *agbp; xfs_agino_t agino; @@ -732,7 +713,7 @@ xfs_inumbers( while (left > 0 && agno < mp->m_sb.sb_agcount) { if (agbp == NULL) { down_read(&mp->m_peraglock); - error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); + error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); up_read(&mp->m_peraglock); if (error) { /* @@ -745,13 +726,13 @@ xfs_inumbers( agino = 0; continue; } - cur = xfs_btree_init_cursor(mp, tp, agbp, agno, + cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO, (xfs_inode_t *)0, 0); error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp); if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); cur = NULL; - xfs_trans_brelse(tp, agbp); + xfs_buf_relse(agbp); agbp = NULL; /* * Move up the the last inode in the current @@ -765,7 +746,7 @@ xfs_inumbers( if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree, &i, ARCH_NOCONVERT)) || i == 0) { - xfs_trans_brelse(tp, agbp); + xfs_buf_relse(agbp); agbp = NULL; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); cur = NULL; @@ -785,7 +766,7 @@ xfs_inumbers( error = XFS_ERROR(EFAULT); break; } - ubuffer += bufidx * sizeof(*buffer); + ubuffer += bufidx; *count += bufidx; bufidx = 0; } @@ -794,7 +775,7 @@ xfs_inumbers( if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); cur = NULL; - xfs_trans_brelse(tp, agbp); + xfs_buf_relse(agbp); agbp = NULL; /* * The agino value has already been bumped. @@ -820,6 +801,6 @@ xfs_inumbers( xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR)); if (agbp) - xfs_trans_brelse(tp, agbp); + xfs_buf_relse(agbp); return error; }