--- /dev/null
+From 31abdab9c11bb1694ecd1476a7edbe8e964d94ac Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 18 May 2013 02:38:52 -0400
+Subject: hpfs: deadlock and race in directory lseek()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 31abdab9c11bb1694ecd1476a7edbe8e964d94ac upstream.
+
+For one thing, there's an ABBA deadlock on hpfs fs-wide lock and i_mutex
+in hpfs_dir_lseek() - there's a lot of methods that grab the former with
+the caller already holding the latter, so it must take i_mutex first.
+
+For another, locking the damn thing, carefully validating the offset,
+then dropping locks and assigning the offset is obviously racy.
+
+Moreover, we _must_ do hpfs_add_pos(), or the machinery in dnode.c
+won't modify the sucker on B-tree surgeries.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hpfs/dir.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/hpfs/dir.c
++++ b/fs/hpfs/dir.c
+@@ -33,25 +33,27 @@ static loff_t hpfs_dir_lseek(struct file
+ if (whence == SEEK_DATA || whence == SEEK_HOLE)
+ return -EINVAL;
+
++ mutex_lock(&i->i_mutex);
+ hpfs_lock(s);
+
+ /*printk("dir lseek\n");*/
+ if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
+- mutex_lock(&i->i_mutex);
+ pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
+ while (pos != new_off) {
+ if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
+ else goto fail;
+ if (pos == 12) goto fail;
+ }
+- mutex_unlock(&i->i_mutex);
++ hpfs_add_pos(i, &filp->f_pos);
+ ok:
++ filp->f_pos = new_off;
+ hpfs_unlock(s);
+- return filp->f_pos = new_off;
+-fail:
+ mutex_unlock(&i->i_mutex);
++ return new_off;
++fail:
+ /*printk("illegal lseek: %016llx\n", new_off);*/
+ hpfs_unlock(s);
++ mutex_unlock(&i->i_mutex);
+ return -ESPIPE;
+ }
+