diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 36f92f181d2f6d58a306109b77566e195254d8e1..28aa81eae2cc6ddee6a2c41c5dee99254ea90f75 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -161,15 +161,25 @@ static int fuse_release(struct inode *inode, struct file *file)
 }
 
 /*
- * It would be nice to scramble the ID space, so that the value of the
- * files_struct pointer is not exposed to userspace.  Symmetric crypto
- * functions are overkill, since the inverse function doesn't need to
- * be implemented (though it does have to exist).  Is there something
- * simpler?
+ * Scramble the ID space with XTEA, so that the value of the files_struct
+ * pointer is not exposed to userspace.
  */
-static inline u64 fuse_lock_owner_id(fl_owner_t id)
+static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 {
-	return (unsigned long) id;
+	u32 *k = fc->scramble_key;
+	u64 v = (unsigned long) id;
+	u32 v0 = v;
+	u32 v1 = v >> 32;
+	u32 sum = 0;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
+		sum += 0x9E3779B9;
+		v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
+	}
+
+	return (u64) v0 + ((u64) v1 << 32);
 }
 
 static int fuse_flush(struct file *file, fl_owner_t id)
@@ -190,7 +200,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 	req = fuse_get_req_nofail(fc, file);
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
-	inarg.lock_owner = fuse_lock_owner_id(id);
+	inarg.lock_owner = fuse_lock_owner_id(fc, id);
 	req->in.h.opcode = FUSE_FLUSH;
 	req->in.h.nodeid = get_node_id(inode);
 	req->in.numargs = 1;
@@ -644,11 +654,12 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
 			 const struct file_lock *fl, int opcode, pid_t pid)
 {
 	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_file *ff = file->private_data;
 	struct fuse_lk_in *arg = &req->misc.lk_in;
 
 	arg->fh = ff->fh;
-	arg->owner = fuse_lock_owner_id(fl->fl_owner);
+	arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
 	arg->lk.start = fl->fl_start;
 	arg->lk.end = fl->fl_end;
 	arg->lk.type = fl->fl_type;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index c862df58da925588954d24dc11bfece621176668..0dbf96621841506f94ed62ae32260fd077ae19d5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -359,6 +359,9 @@ struct fuse_conn {
 
 	/** O_ASYNC requests */
 	struct fasync_struct *fasync;
+
+	/** Key for lock owner ID scrambling */
+	u32 scramble_key[4];
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e21ef8a3ad30bebc15c1155e1730f9e80da95cfa..5ceb8bd7a189ed0967451b56d655083fe5df6467 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/parser.h>
 #include <linux/statfs.h>
+#include <linux/random.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -387,6 +388,7 @@ static struct fuse_conn *new_conn(void)
 		fc->bdi.unplug_io_fn = default_unplug_io_fn;
 		fc->reqctr = 0;
 		fc->blocked = 1;
+		get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 	}
 	return fc;
 }