diff options
-rw-r--r-- | fs/read_write.c | 58 |
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 | ||
32 | EXPORT_SYMBOL(generic_ro_fops); | 32 | EXPORT_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 | */ | ||
34 | loff_t | 43 | loff_t |
35 | generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin) | 44 | generic_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 | } |
58 | EXPORT_SYMBOL(generic_file_llseek_unlocked); | 68 | EXPORT_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 | */ | ||
60 | loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) | 80 | loff_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 | } |
68 | EXPORT_SYMBOL(generic_file_llseek); | 90 | EXPORT_SYMBOL(generic_file_llseek); |
69 | 91 | ||