aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/read_write.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/fs/read_write.c b/fs/read_write.c
index 9ba495d5a29b..969a6d9c020b 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -31,39 +31,61 @@ const struct file_operations generic_ro_fops = {
31 31
32EXPORT_SYMBOL(generic_ro_fops); 32EXPORT_SYMBOL(generic_ro_fops);
33 33
34/**
35 * generic_file_llseek_unlocked - lockless generic llseek implementation
36 * @file: file structure to seek on
37 * @offset: file offset to seek to
38 * @origin: type of seek
39 *
40 * Updates the file offset to the value specified by @offset and @origin.
41 * Locking must be provided by the caller.
42 */
34loff_t 43loff_t
35generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin) 44generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
36{ 45{
37 loff_t retval;
38 struct inode *inode = file->f_mapping->host; 46 struct inode *inode = file->f_mapping->host;
39 47
40 switch (origin) { 48 switch (origin) {
41 case SEEK_END: 49 case SEEK_END:
42 offset += inode->i_size; 50 offset += inode->i_size;
43 break; 51 break;
44 case SEEK_CUR: 52 case SEEK_CUR:
45 offset += file->f_pos; 53 offset += file->f_pos;
54 break;
46 } 55 }
47 retval = -EINVAL; 56
48 if (offset>=0 && offset<=inode->i_sb->s_maxbytes) { 57 if (offset < 0 || offset > inode->i_sb->s_maxbytes)
49 /* Special lock needed here? */ 58 return -EINVAL;
50 if (offset != file->f_pos) { 59
51 file->f_pos = offset; 60 /* Special lock needed here? */
52 file->f_version = 0; 61 if (offset != file->f_pos) {
53 } 62 file->f_pos = offset;
54 retval = offset; 63 file->f_version = 0;
55 } 64 }
56 return retval; 65
66 return offset;
57} 67}
58EXPORT_SYMBOL(generic_file_llseek_unlocked); 68EXPORT_SYMBOL(generic_file_llseek_unlocked);
59 69
70/**
71 * generic_file_llseek - generic llseek implementation for regular files
72 * @file: file structure to seek on
73 * @offset: file offset to seek to
74 * @origin: type of seek
75 *
76 * This is a generic implemenation of ->llseek useable for all normal local
77 * filesystems. It just updates the file offset to the value specified by
78 * @offset and @origin under i_mutex.
79 */
60loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) 80loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
61{ 81{
62 loff_t n; 82 loff_t rval;
83
63 mutex_lock(&file->f_dentry->d_inode->i_mutex); 84 mutex_lock(&file->f_dentry->d_inode->i_mutex);
64 n = generic_file_llseek_unlocked(file, offset, origin); 85 rval = generic_file_llseek_unlocked(file, offset, origin);
65 mutex_unlock(&file->f_dentry->d_inode->i_mutex); 86 mutex_unlock(&file->f_dentry->d_inode->i_mutex);
66 return n; 87
88 return rval;
67} 89}
68EXPORT_SYMBOL(generic_file_llseek); 90EXPORT_SYMBOL(generic_file_llseek);
69 91