diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 225 |
1 files changed, 54 insertions, 171 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 344948082819..a550546a7083 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <linux/log2.h> | ||
19 | |||
18 | #include "xfs.h" | 20 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 21 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 22 | #include "xfs_types.h" |
@@ -826,15 +828,17 @@ xfs_ip2xflags( | |||
826 | xfs_icdinode_t *dic = &ip->i_d; | 828 | xfs_icdinode_t *dic = &ip->i_d; |
827 | 829 | ||
828 | return _xfs_dic2xflags(dic->di_flags) | | 830 | return _xfs_dic2xflags(dic->di_flags) | |
829 | (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); | 831 | (XFS_IFORK_Q(ip) ? XFS_XFLAG_HASATTR : 0); |
830 | } | 832 | } |
831 | 833 | ||
832 | uint | 834 | uint |
833 | xfs_dic2xflags( | 835 | xfs_dic2xflags( |
834 | xfs_dinode_core_t *dic) | 836 | xfs_dinode_t *dip) |
835 | { | 837 | { |
838 | xfs_dinode_core_t *dic = &dip->di_core; | ||
839 | |||
836 | return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) | | 840 | return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) | |
837 | (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); | 841 | (XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0); |
838 | } | 842 | } |
839 | 843 | ||
840 | /* | 844 | /* |
@@ -884,8 +888,8 @@ xfs_iread( | |||
884 | * Initialize inode's trace buffers. | 888 | * Initialize inode's trace buffers. |
885 | * Do this before xfs_iformat in case it adds entries. | 889 | * Do this before xfs_iformat in case it adds entries. |
886 | */ | 890 | */ |
887 | #ifdef XFS_VNODE_TRACE | 891 | #ifdef XFS_INODE_TRACE |
888 | ip->i_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); | 892 | ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_SLEEP); |
889 | #endif | 893 | #endif |
890 | #ifdef XFS_BMAP_TRACE | 894 | #ifdef XFS_BMAP_TRACE |
891 | ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP); | 895 | ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP); |
@@ -1220,10 +1224,8 @@ xfs_ialloc( | |||
1220 | ip->i_d.di_extsize = pip->i_d.di_extsize; | 1224 | ip->i_d.di_extsize = pip->i_d.di_extsize; |
1221 | } | 1225 | } |
1222 | } else if ((mode & S_IFMT) == S_IFREG) { | 1226 | } else if ((mode & S_IFMT) == S_IFREG) { |
1223 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { | 1227 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) |
1224 | di_flags |= XFS_DIFLAG_REALTIME; | 1228 | di_flags |= XFS_DIFLAG_REALTIME; |
1225 | ip->i_iocore.io_flags |= XFS_IOCORE_RT; | ||
1226 | } | ||
1227 | if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { | 1229 | if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { |
1228 | di_flags |= XFS_DIFLAG_EXTSIZE; | 1230 | di_flags |= XFS_DIFLAG_EXTSIZE; |
1229 | ip->i_d.di_extsize = pip->i_d.di_extsize; | 1231 | ip->i_d.di_extsize = pip->i_d.di_extsize; |
@@ -1298,7 +1300,10 @@ xfs_isize_check( | |||
1298 | if ((ip->i_d.di_mode & S_IFMT) != S_IFREG) | 1300 | if ((ip->i_d.di_mode & S_IFMT) != S_IFREG) |
1299 | return; | 1301 | return; |
1300 | 1302 | ||
1301 | if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE)) | 1303 | if (XFS_IS_REALTIME_INODE(ip)) |
1304 | return; | ||
1305 | |||
1306 | if (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) | ||
1302 | return; | 1307 | return; |
1303 | 1308 | ||
1304 | nimaps = 2; | 1309 | nimaps = 2; |
@@ -1711,7 +1716,7 @@ xfs_itruncate_finish( | |||
1711 | * runs. | 1716 | * runs. |
1712 | */ | 1717 | */ |
1713 | XFS_BMAP_INIT(&free_list, &first_block); | 1718 | XFS_BMAP_INIT(&free_list, &first_block); |
1714 | error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore, | 1719 | error = xfs_bunmapi(ntp, ip, |
1715 | first_unmap_block, unmap_len, | 1720 | first_unmap_block, unmap_len, |
1716 | XFS_BMAPI_AFLAG(fork) | | 1721 | XFS_BMAPI_AFLAG(fork) | |
1717 | (sync ? 0 : XFS_BMAPI_ASYNC), | 1722 | (sync ? 0 : XFS_BMAPI_ASYNC), |
@@ -1844,8 +1849,6 @@ xfs_igrow_start( | |||
1844 | xfs_fsize_t new_size, | 1849 | xfs_fsize_t new_size, |
1845 | cred_t *credp) | 1850 | cred_t *credp) |
1846 | { | 1851 | { |
1847 | int error; | ||
1848 | |||
1849 | ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0); | 1852 | ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0); |
1850 | ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0); | 1853 | ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0); |
1851 | ASSERT(new_size > ip->i_size); | 1854 | ASSERT(new_size > ip->i_size); |
@@ -1855,9 +1858,7 @@ xfs_igrow_start( | |||
1855 | * xfs_write_file() beyond the end of the file | 1858 | * xfs_write_file() beyond the end of the file |
1856 | * and any blocks between the old and new file sizes. | 1859 | * and any blocks between the old and new file sizes. |
1857 | */ | 1860 | */ |
1858 | error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, | 1861 | return xfs_zero_eof(ip, new_size, ip->i_size); |
1859 | ip->i_size); | ||
1860 | return error; | ||
1861 | } | 1862 | } |
1862 | 1863 | ||
1863 | /* | 1864 | /* |
@@ -1959,24 +1960,6 @@ xfs_iunlink( | |||
1959 | ASSERT(agi->agi_unlinked[bucket_index]); | 1960 | ASSERT(agi->agi_unlinked[bucket_index]); |
1960 | ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino); | 1961 | ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino); |
1961 | 1962 | ||
1962 | error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); | ||
1963 | if (error) | ||
1964 | return error; | ||
1965 | |||
1966 | /* | ||
1967 | * Clear the on-disk di_nlink. This is to prevent xfs_bulkstat | ||
1968 | * from picking up this inode when it is reclaimed (its incore state | ||
1969 | * initialzed but not flushed to disk yet). The in-core di_nlink is | ||
1970 | * already cleared in xfs_droplink() and a corresponding transaction | ||
1971 | * logged. The hack here just synchronizes the in-core to on-disk | ||
1972 | * di_nlink value in advance before the actual inode sync to disk. | ||
1973 | * This is OK because the inode is already unlinked and would never | ||
1974 | * change its di_nlink again for this inode generation. | ||
1975 | * This is a temporary hack that would require a proper fix | ||
1976 | * in the future. | ||
1977 | */ | ||
1978 | dip->di_core.di_nlink = 0; | ||
1979 | |||
1980 | if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) { | 1963 | if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) { |
1981 | /* | 1964 | /* |
1982 | * There is already another inode in the bucket we need | 1965 | * There is already another inode in the bucket we need |
@@ -1984,6 +1967,10 @@ xfs_iunlink( | |||
1984 | * Here we put the head pointer into our next pointer, | 1967 | * Here we put the head pointer into our next pointer, |
1985 | * and then we fall through to point the head at us. | 1968 | * and then we fall through to point the head at us. |
1986 | */ | 1969 | */ |
1970 | error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0); | ||
1971 | if (error) | ||
1972 | return error; | ||
1973 | |||
1987 | ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO); | 1974 | ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO); |
1988 | /* both on-disk, don't endian flip twice */ | 1975 | /* both on-disk, don't endian flip twice */ |
1989 | dip->di_next_unlinked = agi->agi_unlinked[bucket_index]; | 1976 | dip->di_next_unlinked = agi->agi_unlinked[bucket_index]; |
@@ -2209,7 +2196,6 @@ xfs_ifree_cluster( | |||
2209 | xfs_inode_log_item_t *iip; | 2196 | xfs_inode_log_item_t *iip; |
2210 | xfs_log_item_t *lip; | 2197 | xfs_log_item_t *lip; |
2211 | xfs_perag_t *pag = xfs_get_perag(mp, inum); | 2198 | xfs_perag_t *pag = xfs_get_perag(mp, inum); |
2212 | SPLDECL(s); | ||
2213 | 2199 | ||
2214 | if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) { | 2200 | if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) { |
2215 | blks_per_cluster = 1; | 2201 | blks_per_cluster = 1; |
@@ -2311,9 +2297,9 @@ xfs_ifree_cluster( | |||
2311 | iip = (xfs_inode_log_item_t *)lip; | 2297 | iip = (xfs_inode_log_item_t *)lip; |
2312 | ASSERT(iip->ili_logged == 1); | 2298 | ASSERT(iip->ili_logged == 1); |
2313 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; | 2299 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; |
2314 | AIL_LOCK(mp,s); | 2300 | spin_lock(&mp->m_ail_lock); |
2315 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2301 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
2316 | AIL_UNLOCK(mp, s); | 2302 | spin_unlock(&mp->m_ail_lock); |
2317 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); | 2303 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); |
2318 | pre_flushed++; | 2304 | pre_flushed++; |
2319 | } | 2305 | } |
@@ -2334,9 +2320,9 @@ xfs_ifree_cluster( | |||
2334 | iip->ili_last_fields = iip->ili_format.ilf_fields; | 2320 | iip->ili_last_fields = iip->ili_format.ilf_fields; |
2335 | iip->ili_format.ilf_fields = 0; | 2321 | iip->ili_format.ilf_fields = 0; |
2336 | iip->ili_logged = 1; | 2322 | iip->ili_logged = 1; |
2337 | AIL_LOCK(mp,s); | 2323 | spin_lock(&mp->m_ail_lock); |
2338 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2324 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
2339 | AIL_UNLOCK(mp, s); | 2325 | spin_unlock(&mp->m_ail_lock); |
2340 | 2326 | ||
2341 | xfs_buf_attach_iodone(bp, | 2327 | xfs_buf_attach_iodone(bp, |
2342 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 2328 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) |
@@ -2374,6 +2360,8 @@ xfs_ifree( | |||
2374 | int error; | 2360 | int error; |
2375 | int delete; | 2361 | int delete; |
2376 | xfs_ino_t first_ino; | 2362 | xfs_ino_t first_ino; |
2363 | xfs_dinode_t *dip; | ||
2364 | xfs_buf_t *ibp; | ||
2377 | 2365 | ||
2378 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); | 2366 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); |
2379 | ASSERT(ip->i_transp == tp); | 2367 | ASSERT(ip->i_transp == tp); |
@@ -2409,8 +2397,27 @@ xfs_ifree( | |||
2409 | * by reincarnations of this inode. | 2397 | * by reincarnations of this inode. |
2410 | */ | 2398 | */ |
2411 | ip->i_d.di_gen++; | 2399 | ip->i_d.di_gen++; |
2400 | |||
2412 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 2401 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
2413 | 2402 | ||
2403 | error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0); | ||
2404 | if (error) | ||
2405 | return error; | ||
2406 | |||
2407 | /* | ||
2408 | * Clear the on-disk di_mode. This is to prevent xfs_bulkstat | ||
2409 | * from picking up this inode when it is reclaimed (its incore state | ||
2410 | * initialzed but not flushed to disk yet). The in-core di_mode is | ||
2411 | * already cleared and a corresponding transaction logged. | ||
2412 | * The hack here just synchronizes the in-core to on-disk | ||
2413 | * di_mode value in advance before the actual inode sync to disk. | ||
2414 | * This is OK because the inode is already unlinked and would never | ||
2415 | * change its di_mode again for this inode generation. | ||
2416 | * This is a temporary hack that would require a proper fix | ||
2417 | * in the future. | ||
2418 | */ | ||
2419 | dip->di_core.di_mode = 0; | ||
2420 | |||
2414 | if (delete) { | 2421 | if (delete) { |
2415 | xfs_ifree_cluster(ip, tp, first_ino); | 2422 | xfs_ifree_cluster(ip, tp, first_ino); |
2416 | } | 2423 | } |
@@ -2735,7 +2742,6 @@ void | |||
2735 | xfs_idestroy( | 2742 | xfs_idestroy( |
2736 | xfs_inode_t *ip) | 2743 | xfs_inode_t *ip) |
2737 | { | 2744 | { |
2738 | |||
2739 | switch (ip->i_d.di_mode & S_IFMT) { | 2745 | switch (ip->i_d.di_mode & S_IFMT) { |
2740 | case S_IFREG: | 2746 | case S_IFREG: |
2741 | case S_IFDIR: | 2747 | case S_IFDIR: |
@@ -2749,7 +2755,7 @@ xfs_idestroy( | |||
2749 | mrfree(&ip->i_iolock); | 2755 | mrfree(&ip->i_iolock); |
2750 | freesema(&ip->i_flock); | 2756 | freesema(&ip->i_flock); |
2751 | 2757 | ||
2752 | #ifdef XFS_VNODE_TRACE | 2758 | #ifdef XFS_INODE_TRACE |
2753 | ktrace_free(ip->i_trace); | 2759 | ktrace_free(ip->i_trace); |
2754 | #endif | 2760 | #endif |
2755 | #ifdef XFS_BMAP_TRACE | 2761 | #ifdef XFS_BMAP_TRACE |
@@ -2775,16 +2781,15 @@ xfs_idestroy( | |||
2775 | */ | 2781 | */ |
2776 | xfs_mount_t *mp = ip->i_mount; | 2782 | xfs_mount_t *mp = ip->i_mount; |
2777 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | 2783 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; |
2778 | int s; | ||
2779 | 2784 | ||
2780 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | 2785 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || |
2781 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | 2786 | XFS_FORCED_SHUTDOWN(ip->i_mount)); |
2782 | if (lip->li_flags & XFS_LI_IN_AIL) { | 2787 | if (lip->li_flags & XFS_LI_IN_AIL) { |
2783 | AIL_LOCK(mp, s); | 2788 | spin_lock(&mp->m_ail_lock); |
2784 | if (lip->li_flags & XFS_LI_IN_AIL) | 2789 | if (lip->li_flags & XFS_LI_IN_AIL) |
2785 | xfs_trans_delete_ail(mp, lip, s); | 2790 | xfs_trans_delete_ail(mp, lip); |
2786 | else | 2791 | else |
2787 | AIL_UNLOCK(mp, s); | 2792 | spin_unlock(&mp->m_ail_lock); |
2788 | } | 2793 | } |
2789 | xfs_inode_item_destroy(ip); | 2794 | xfs_inode_item_destroy(ip); |
2790 | } | 2795 | } |
@@ -2816,40 +2821,8 @@ xfs_iunpin( | |||
2816 | { | 2821 | { |
2817 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 2822 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
2818 | 2823 | ||
2819 | if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { | 2824 | if (atomic_dec_and_test(&ip->i_pincount)) |
2820 | |||
2821 | /* | ||
2822 | * If the inode is currently being reclaimed, the link between | ||
2823 | * the bhv_vnode and the xfs_inode will be broken after the | ||
2824 | * XFS_IRECLAIM* flag is set. Hence, if these flags are not | ||
2825 | * set, then we can move forward and mark the linux inode dirty | ||
2826 | * knowing that it is still valid as it won't freed until after | ||
2827 | * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The | ||
2828 | * i_flags_lock is used to synchronise the setting of the | ||
2829 | * XFS_IRECLAIM* flags and the breaking of the link, and so we | ||
2830 | * can execute atomically w.r.t to reclaim by holding this lock | ||
2831 | * here. | ||
2832 | * | ||
2833 | * However, we still need to issue the unpin wakeup call as the | ||
2834 | * inode reclaim may be blocked waiting for the inode to become | ||
2835 | * unpinned. | ||
2836 | */ | ||
2837 | |||
2838 | if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { | ||
2839 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); | ||
2840 | struct inode *inode = NULL; | ||
2841 | |||
2842 | BUG_ON(vp == NULL); | ||
2843 | inode = vn_to_inode(vp); | ||
2844 | BUG_ON(inode->i_state & I_CLEAR); | ||
2845 | |||
2846 | /* make sync come back and flush this inode */ | ||
2847 | if (!(inode->i_state & (I_NEW|I_FREEING))) | ||
2848 | mark_inode_dirty_sync(inode); | ||
2849 | } | ||
2850 | spin_unlock(&ip->i_flags_lock); | ||
2851 | wake_up(&ip->i_ipin_wait); | 2825 | wake_up(&ip->i_ipin_wait); |
2852 | } | ||
2853 | } | 2826 | } |
2854 | 2827 | ||
2855 | /* | 2828 | /* |
@@ -3338,7 +3311,6 @@ xfs_iflush_int( | |||
3338 | #ifdef XFS_TRANS_DEBUG | 3311 | #ifdef XFS_TRANS_DEBUG |
3339 | int first; | 3312 | int first; |
3340 | #endif | 3313 | #endif |
3341 | SPLDECL(s); | ||
3342 | 3314 | ||
3343 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); | 3315 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); |
3344 | ASSERT(issemalocked(&(ip->i_flock))); | 3316 | ASSERT(issemalocked(&(ip->i_flock))); |
@@ -3533,9 +3505,9 @@ xfs_iflush_int( | |||
3533 | iip->ili_logged = 1; | 3505 | iip->ili_logged = 1; |
3534 | 3506 | ||
3535 | ASSERT(sizeof(xfs_lsn_t) == 8); /* don't lock if it shrinks */ | 3507 | ASSERT(sizeof(xfs_lsn_t) == 8); /* don't lock if it shrinks */ |
3536 | AIL_LOCK(mp,s); | 3508 | spin_lock(&mp->m_ail_lock); |
3537 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 3509 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
3538 | AIL_UNLOCK(mp, s); | 3510 | spin_unlock(&mp->m_ail_lock); |
3539 | 3511 | ||
3540 | /* | 3512 | /* |
3541 | * Attach the function xfs_iflush_done to the inode's | 3513 | * Attach the function xfs_iflush_done to the inode's |
@@ -3611,95 +3583,6 @@ xfs_iflush_all( | |||
3611 | XFS_MOUNT_IUNLOCK(mp); | 3583 | XFS_MOUNT_IUNLOCK(mp); |
3612 | } | 3584 | } |
3613 | 3585 | ||
3614 | /* | ||
3615 | * xfs_iaccess: check accessibility of inode for mode. | ||
3616 | */ | ||
3617 | int | ||
3618 | xfs_iaccess( | ||
3619 | xfs_inode_t *ip, | ||
3620 | mode_t mode, | ||
3621 | cred_t *cr) | ||
3622 | { | ||
3623 | int error; | ||
3624 | mode_t orgmode = mode; | ||
3625 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); | ||
3626 | |||
3627 | if (mode & S_IWUSR) { | ||
3628 | umode_t imode = inode->i_mode; | ||
3629 | |||
3630 | if (IS_RDONLY(inode) && | ||
3631 | (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode))) | ||
3632 | return XFS_ERROR(EROFS); | ||
3633 | |||
3634 | if (IS_IMMUTABLE(inode)) | ||
3635 | return XFS_ERROR(EACCES); | ||
3636 | } | ||
3637 | |||
3638 | /* | ||
3639 | * If there's an Access Control List it's used instead of | ||
3640 | * the mode bits. | ||
3641 | */ | ||
3642 | if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1) | ||
3643 | return error ? XFS_ERROR(error) : 0; | ||
3644 | |||
3645 | if (current_fsuid(cr) != ip->i_d.di_uid) { | ||
3646 | mode >>= 3; | ||
3647 | if (!in_group_p((gid_t)ip->i_d.di_gid)) | ||
3648 | mode >>= 3; | ||
3649 | } | ||
3650 | |||
3651 | /* | ||
3652 | * If the DACs are ok we don't need any capability check. | ||
3653 | */ | ||
3654 | if ((ip->i_d.di_mode & mode) == mode) | ||
3655 | return 0; | ||
3656 | /* | ||
3657 | * Read/write DACs are always overridable. | ||
3658 | * Executable DACs are overridable if at least one exec bit is set. | ||
3659 | */ | ||
3660 | if (!(orgmode & S_IXUSR) || | ||
3661 | (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode)) | ||
3662 | if (capable_cred(cr, CAP_DAC_OVERRIDE)) | ||
3663 | return 0; | ||
3664 | |||
3665 | if ((orgmode == S_IRUSR) || | ||
3666 | (S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) { | ||
3667 | if (capable_cred(cr, CAP_DAC_READ_SEARCH)) | ||
3668 | return 0; | ||
3669 | #ifdef NOISE | ||
3670 | cmn_err(CE_NOTE, "Ick: mode=%o, orgmode=%o", mode, orgmode); | ||
3671 | #endif /* NOISE */ | ||
3672 | return XFS_ERROR(EACCES); | ||
3673 | } | ||
3674 | return XFS_ERROR(EACCES); | ||
3675 | } | ||
3676 | |||
3677 | /* | ||
3678 | * xfs_iroundup: round up argument to next power of two | ||
3679 | */ | ||
3680 | uint | ||
3681 | xfs_iroundup( | ||
3682 | uint v) | ||
3683 | { | ||
3684 | int i; | ||
3685 | uint m; | ||
3686 | |||
3687 | if ((v & (v - 1)) == 0) | ||
3688 | return v; | ||
3689 | ASSERT((v & 0x80000000) == 0); | ||
3690 | if ((v & (v + 1)) == 0) | ||
3691 | return v + 1; | ||
3692 | for (i = 0, m = 1; i < 31; i++, m <<= 1) { | ||
3693 | if (v & m) | ||
3694 | continue; | ||
3695 | v |= m; | ||
3696 | if ((v & (v + 1)) == 0) | ||
3697 | return v + 1; | ||
3698 | } | ||
3699 | ASSERT(0); | ||
3700 | return( 0 ); | ||
3701 | } | ||
3702 | |||
3703 | #ifdef XFS_ILOCK_TRACE | 3586 | #ifdef XFS_ILOCK_TRACE |
3704 | ktrace_t *xfs_ilock_trace_buf; | 3587 | ktrace_t *xfs_ilock_trace_buf; |
3705 | 3588 | ||
@@ -4206,7 +4089,7 @@ xfs_iext_realloc_direct( | |||
4206 | return; | 4089 | return; |
4207 | } | 4090 | } |
4208 | if (!is_power_of_2(new_size)){ | 4091 | if (!is_power_of_2(new_size)){ |
4209 | rnew_size = xfs_iroundup(new_size); | 4092 | rnew_size = roundup_pow_of_two(new_size); |
4210 | } | 4093 | } |
4211 | if (rnew_size != ifp->if_real_bytes) { | 4094 | if (rnew_size != ifp->if_real_bytes) { |
4212 | ifp->if_u1.if_extents = | 4095 | ifp->if_u1.if_extents = |
@@ -4229,7 +4112,7 @@ xfs_iext_realloc_direct( | |||
4229 | else { | 4112 | else { |
4230 | new_size += ifp->if_bytes; | 4113 | new_size += ifp->if_bytes; |
4231 | if (!is_power_of_2(new_size)) { | 4114 | if (!is_power_of_2(new_size)) { |
4232 | rnew_size = xfs_iroundup(new_size); | 4115 | rnew_size = roundup_pow_of_two(new_size); |
4233 | } | 4116 | } |
4234 | xfs_iext_inline_to_direct(ifp, rnew_size); | 4117 | xfs_iext_inline_to_direct(ifp, rnew_size); |
4235 | } | 4118 | } |