After the BKL removal patches were applied to the rest of the NFS code, the
BKL protection in nfs_file_llseek() is no longer sufficient to ensure that
inode->i_size is read safely in generic_file_llseek_unlocked().
In order to fix the situation, we either have to replace the naked read of
inode->i_size in generic_file_llseek_unlocked() with i_size_read(), or the
whole thing needs to be executed under the inode->i_lock;
In order to avoid disrupting other filesystems, avoid touching
generic_file_llseek_unlocked() for now...
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
        /* origin == SEEK_END => we must revalidate the cached file length */
        if (origin == SEEK_END) {
                struct inode *inode = filp->f_mapping->host;
+
                int retval = nfs_revalidate_file_size(inode, filp);
                if (retval < 0)
                        return (loff_t)retval;
-       }
-       lock_kernel();  /* BKL needed? */
-       loff = generic_file_llseek_unlocked(filp, offset, origin);
-       unlock_kernel();
+
+               spin_lock(&inode->i_lock);
+               loff = generic_file_llseek_unlocked(filp, offset, origin);
+               spin_unlock(&inode->i_lock);
+       } else
+               loff = generic_file_llseek_unlocked(filp, offset, origin);
        return loff;
 }