All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andi Kleen <andi@firstfloor.org>
To: viro@zeniv.linux.org.uk
Cc: hch@infradead.org, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, Andi Kleen <ak@linux.intel.com>
Subject: [PATCH 2/5] VFS: Use f_lock for SEEK_SET
Date: Thu, 16 Jun 2011 14:07:19 -0700	[thread overview]
Message-ID: <1308258442-19804-2-git-send-email-andi@firstfloor.org> (raw)
In-Reply-To: <1308258442-19804-1-git-send-email-andi@firstfloor.org>

From: Andi Kleen <ak@linux.intel.com>

Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
 fs/read_write.c    |   44 ++++++++++++++++++++++++++++++--------------
 include/linux/fs.h |    3 ++-
 2 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index 9bd5d23..0b1d4ca 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -35,6 +35,20 @@ static inline int unsigned_offsets(struct file *file)
 	return file->f_mode & FMODE_UNSIGNED_OFFSET;
 }
 
+static loff_t lseek_execute(struct file *file, struct inode *inode, loff_t offset)
+{
+	if (offset < 0 && !unsigned_offsets(file))
+		return -EINVAL;
+	if (offset > inode->i_sb->s_maxbytes)
+		return -EINVAL;
+
+	if (offset != file->f_pos) {
+		file->f_pos = offset;
+		file->f_version = 0;
+	}	
+	return offset;
+}
+
 /**
  * generic_file_llseek - generic llseek implementation for regular files
  * @file:	file structure to seek on
@@ -44,6 +58,12 @@ static inline int unsigned_offsets(struct file *file)
  * This is a generic implemenation of ->llseek useable for all normal local
  * filesystems.  It just updates the file offset to the value specified by
  * @offset and @origin under i_mutex.
+ * 
+ * Synchronization: 
+ * SEEK_SET is unsynchronized (but atomic on 64bit platforms)
+ * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes.
+ * read/writes behave like SEEK_SET against seeks.
+ * SEEK_END 
  */
 loff_t
 generic_file_llseek(struct file *file, loff_t offset, int origin)
@@ -63,22 +83,18 @@ generic_file_llseek(struct file *file, loff_t offset, int origin)
 		 */
 		if (offset == 0)
 			return file->f_pos;
-		offset += file->f_pos;
-		break;
-	}
-
-	if (offset < 0 && !unsigned_offsets(file))
-		return -EINVAL;
-	if (offset > inode->i_sb->s_maxbytes)
-		return -EINVAL;
-
-	/* Special lock needed here? */
-	if (offset != file->f_pos) {
-		file->f_pos = offset;
-		file->f_version = 0;
+		/* 
+		 * f_lock protects against read/modify/write race with other
+		 * SEEK_CURs. Note that parallel writes and reads behave
+		 * like SEEK_SET.
+		 */
+		spin_lock(&file->f_lock);
+		offset = lseek_execute(file, inode, offset + file->f_pos);
+		spin_unlock(&file->f_lock);
+		return offset;
 	}
 
-	return offset;
+	return lseek_execute(file, inode, offset);
 }
 EXPORT_SYMBOL(generic_file_llseek);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index deec2cd..a19d164 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -946,7 +946,8 @@ struct file {
 #define f_dentry	f_path.dentry
 #define f_vfsmnt	f_path.mnt
 	const struct file_operations	*f_op;
-	spinlock_t		f_lock;  /* f_ep_links, f_flags, no IRQ */
+	spinlock_t		f_lock;  /* f_ep_links, f_flags, no IRQ, 
+					    SEEK_SET */
 #ifdef CONFIG_SMP
 	int			f_sb_list_cpu;
 #endif
-- 
1.7.4.4


  reply	other threads:[~2011-06-16 21:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-16 21:07 [PATCH 1/5] VFS: Do (nearly) lockless generic_file_llseek Andi Kleen
2011-06-16 21:07 ` Andi Kleen [this message]
2011-06-16 21:07 ` [PATCH 3/5] VFS: Add generic_file_llseek_size Andi Kleen
2011-06-16 21:07 ` [PATCH 4/5] EXT4: Replace cut'n'pasted llseek code with generic_file_llseek_size Andi Kleen
2011-06-16 21:07 ` [PATCH 5/5] NFS: Drop unnecessary locking in llseek Andi Kleen
2011-06-17 12:40 ` [PATCH 1/5] VFS: Do (nearly) lockless generic_file_llseek Arnd Bergmann
2011-06-17 17:42   ` Andi Kleen
2011-06-17 21:18     ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1308258442-19804-2-git-send-email-andi@firstfloor.org \
    --to=andi@firstfloor.org \
    --cc=ak@linux.intel.com \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.