diff --git a/fs/read_write.c b/fs/read_write.c
index bb34af3..41f76e5 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -218,14 +218,25 @@ EXPORT_SYMBOL(default_llseek);
 
 loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
 {
+	struct inode *inode = file->f_path.dentry->d_inode;
 	loff_t (*fn)(struct file *, loff_t, int);
+	int ret;
 
 	fn = no_llseek;
 	if (file->f_mode & FMODE_LSEEK) {
 		if (file->f_op && file->f_op->llseek)
 			fn = file->f_op->llseek;
 	}
-	return fn(file, offset, whence);
+
+	if (S_ISDIR(inode->i_mode)) {
+		mutex_lock(&inode->i_mutex);
+		ret = fn(file, offset, whence);
+		mutex_unlock(&inode->i_mutex);
+	} else {
+		ret = fn(file, offset, whence);
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(vfs_llseek);
 
@@ -442,12 +453,32 @@ EXPORT_SYMBOL(vfs_write);
 
 static inline loff_t file_pos_read(struct file *file)
 {
-	return file->f_pos;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	loff_t pos;
+
+	if (S_ISDIR(inode->i_mode)) {
+		mutex_lock(&inode->i_mutex);
+		pos = file->f_pos;
+		mutex_unlock(&inode->i_mutex);
+	} else {
+		pos = file->f_pos;
+	}
+
+	return pos;
 }
 
 static inline void file_pos_write(struct file *file, loff_t pos)
 {
-	file->f_pos = pos;
+	struct inode *inode = file->f_path.dentry->d_inode;
+
+	if (S_ISDIR(inode->i_mode)) {
+		mutex_lock(&inode->i_mutex);
+		file->f_pos = pos;
+		file->f_version = 0;
+		mutex_unlock(&inode->i_mutex);
+	} else {
+		file->f_pos = pos;
+	}
 }
 
 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
