[XFS] Combine the XFS and Linux inodes
[deliverable/linux.git] / fs / xfs / xfs_vnodeops.c
index aa238c8fbd7ae605e9f316969bb3012ee4c32f3c..7fb577c9f9d8daf0d4f60e755d18c5c9f9fe24c8 100644 (file)
@@ -1838,6 +1838,12 @@ again:
 #endif
 }
 
+/*
+ * xfs_lock_two_inodes() can only be used to lock one type of lock
+ * at a time - the iolock or the ilock, but not both at once. If
+ * we lock both at once, lockdep will report false positives saying
+ * we have violated locking orders.
+ */
 void
 xfs_lock_two_inodes(
        xfs_inode_t             *ip0,
@@ -1848,6 +1854,8 @@ xfs_lock_two_inodes(
        int                     attempts = 0;
        xfs_log_item_t          *lp;
 
+       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
+               ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0);
        ASSERT(ip0->i_ino != ip1->i_ino);
 
        if (ip0->i_ino > ip1->i_ino) {
@@ -2825,6 +2833,7 @@ xfs_reclaim(
        if (!ip->i_update_core && (ip->i_itemp == NULL)) {
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                xfs_iflock(ip);
+               xfs_iflags_set(ip, XFS_IRECLAIMABLE);
                return xfs_finish_reclaim(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC);
        } else {
                xfs_mount_t     *mp = ip->i_mount;
@@ -2833,8 +2842,6 @@ xfs_reclaim(
                XFS_MOUNT_ILOCK(mp);
                spin_lock(&ip->i_flags_lock);
                __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
-               VFS_I(ip)->i_private = NULL;
-               ip->i_vnode = NULL;
                spin_unlock(&ip->i_flags_lock);
                list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
                XFS_MOUNT_IUNLOCK(mp);
@@ -2849,10 +2856,6 @@ xfs_finish_reclaim(
        int             sync_mode)
 {
        xfs_perag_t     *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
-       struct inode    *vp = VFS_I(ip);
-
-       if (vp && VN_BAD(vp))
-               goto reclaim;
 
        /* The hash lock here protects a thread in xfs_iget_core from
         * racing with us on linking the inode back with a vnode.
@@ -2862,7 +2865,7 @@ xfs_finish_reclaim(
        write_lock(&pag->pag_ici_lock);
        spin_lock(&ip->i_flags_lock);
        if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
-           (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) {
+           !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
                spin_unlock(&ip->i_flags_lock);
                write_unlock(&pag->pag_ici_lock);
                if (locked) {
@@ -2896,50 +2899,42 @@ xfs_finish_reclaim(
         * In the case of a forced shutdown we rely on xfs_iflush() to
         * wait for the inode to be unpinned before returning an error.
         */
-       if (xfs_iflush(ip, sync_mode) == 0) {
+       if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) {
                /* synchronize with xfs_iflush_done */
                xfs_iflock(ip);
                xfs_ifunlock(ip);
        }
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
- reclaim:
        xfs_ireclaim(ip);
        return 0;
 }
 
 int
-xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
+xfs_finish_reclaim_all(
+       xfs_mount_t     *mp,
+       int              noblock,
+       int             mode)
 {
-       int             purged;
        xfs_inode_t     *ip, *n;
-       int             done = 0;
 
-       while (!done) {
-               purged = 0;
-               XFS_MOUNT_ILOCK(mp);
-               list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) {
-                       if (noblock) {
-                               if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
-                                       continue;
-                               if (xfs_ipincount(ip) ||
-                                   !xfs_iflock_nowait(ip)) {
-                                       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-                                       continue;
-                               }
+restart:
+       XFS_MOUNT_ILOCK(mp);
+       list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) {
+               if (noblock) {
+                       if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
+                               continue;
+                       if (xfs_ipincount(ip) ||
+                           !xfs_iflock_nowait(ip)) {
+                               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+                               continue;
                        }
-                       XFS_MOUNT_IUNLOCK(mp);
-                       if (xfs_finish_reclaim(ip, noblock,
-                                       XFS_IFLUSH_DELWRI_ELSE_ASYNC))
-                               delay(1);
-                       purged = 1;
-                       break;
                }
-
-               done = !purged;
+               XFS_MOUNT_IUNLOCK(mp);
+               if (xfs_finish_reclaim(ip, noblock, mode))
+                       delay(1);
+               goto restart;
        }
-
        XFS_MOUNT_IUNLOCK(mp);
        return 0;
 }
@@ -3152,6 +3147,13 @@ error1:  /* Just cancel transaction */
 /*
  * Zero file bytes between startoff and endoff inclusive.
  * The iolock is held exclusive and no blocks are buffered.
+ *
+ * This function is used by xfs_free_file_space() to zero
+ * partial blocks when the range to free is not block aligned.
+ * When unreserving space with boundaries that are not block
+ * aligned we round up the start and round down the end
+ * boundaries and then use this function to zero the parts of
+ * the blocks that got dropped during the rounding.
  */
 STATIC int
 xfs_zero_remaining_bytes(
@@ -3168,6 +3170,17 @@ xfs_zero_remaining_bytes(
        int                     nimap;
        int                     error = 0;
 
+       /*
+        * Avoid doing I/O beyond eof - it's not necessary
+        * since nothing can read beyond eof.  The space will
+        * be zeroed when the file is extended anyway.
+        */
+       if (startoff >= ip->i_size)
+               return 0;
+
+       if (endoff > ip->i_size)
+               endoff = ip->i_size;
+
        bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize,
                                XFS_IS_REALTIME_INODE(ip) ?
                                mp->m_rtdev_targp : mp->m_ddev_targp);
This page took 0.026311 seconds and 5 git commands to generate.