If a directory has a large number of empty blocks, iterating over all
of them can take a long time, leading to scheduler warnings and users
getting irritated when they can't kill a process in the middle of one
of these long-running readdir operations.  Fix this by adding checks to
ext4_readdir() and ext4_htree_fill_tree().
This was reverted earlier due to a typo in the original commit where I
experimented with using signal_pending() instead of
fatal_signal_pending().  The test was in the wrong place if we were
going to return signal_pending() since we would end up returning
duplicant entries.  See 
9f2394c9be47 for a more detailed explanation.
Added fix as suggested by Linus to check for signal_pending() in
in the filldir() functions.
Reported-by: Benjamin LaHaise <bcrl@kvack.org>
Google-Bug-Id: 
27880676
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
 
        }
        dirent = buf->previous;
        if (dirent) {
+               if (signal_pending(current))
+                       return -EINTR;
                if (__put_user(offset, &dirent->d_off))
                        goto efault;
        }
        dirent = buf->previous;
 
        if (dirent) {
+               if (signal_pending(current))
+                       return -EINTR;
                if (__put_user_unaligned(offset, &dirent->d_off))
                        goto efault;
        }
 
        while (ctx->pos < inode->i_size) {
                struct ext4_map_blocks map;
 
+               if (fatal_signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       goto errout;
+               }
+               cond_resched();
                map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
                map.m_len = 1;
                err = ext4_map_blocks(NULL, inode, &map, 0);
 
        }
 
        while (1) {
+               if (fatal_signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       goto errout;
+               }
+               cond_resched();
                block = dx_get_block(frame->at);
                ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
                                             start_hash, start_minor_hash);
 
        }
        dirent = buf->previous;
        if (dirent) {
+               if (signal_pending(current))
+                       return -EINTR;
                if (__put_user(offset, &dirent->d_off))
                        goto efault;
        }
                return -EINVAL;
        dirent = buf->previous;
        if (dirent) {
+               if (signal_pending(current))
+                       return -EINTR;
                if (__put_user(offset, &dirent->d_off))
                        goto efault;
        }