diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-02-14 06:54:42 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-02-14 06:54:42 -0500 |
commit | d1665e414297c3a46fd80cb8242ad0c8e82acae7 (patch) | |
tree | 7cb19fc4cbfc21d6d890dd3b373d3854920862db /fs/gfs2/ops_file.c | |
parent | fc69d0d336214219abb521d8ff060f786d7f369e (diff) |
[GFS2] Put back O_DIRECT support
This patch adds back O_DIRECT support with various caveats
attached:
1. Journaled data can be read via O_DIRECT since its now the
same on disk format as normal data files.
2. Journaled data writes with O_DIRECT will be failed sliently
back to normal writes (should we really do this I wonder or
should we return an error instead?)
3. Stuffed files will be failed back to normal buffered I/O
4. All the usual corner cases (write beyond current end of file,
write to an unallocated block) will also revert to normal buffered I/O.
The I/O path is slightly odd as reads arrive at the page cache layer
with the lock for the file already held, but writes arrive unlocked.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_file.c')
-rw-r--r-- | fs/gfs2/ops_file.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 56820b39a993..bcde7a0b76f1 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -176,16 +176,16 @@ static ssize_t __gfs2_file_aio_read(struct kiocb *iocb, | |||
176 | * If any segment has a negative length, or the cumulative | 176 | * If any segment has a negative length, or the cumulative |
177 | * length ever wraps negative then return -EINVAL. | 177 | * length ever wraps negative then return -EINVAL. |
178 | */ | 178 | */ |
179 | count += iv->iov_len; | 179 | count += iv->iov_len; |
180 | if (unlikely((ssize_t)(count|iv->iov_len) < 0)) | 180 | if (unlikely((ssize_t)(count|iv->iov_len) < 0)) |
181 | return -EINVAL; | 181 | return -EINVAL; |
182 | if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len)) | 182 | if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len)) |
183 | continue; | 183 | continue; |
184 | if (seg == 0) | 184 | if (seg == 0) |
185 | return -EFAULT; | 185 | return -EFAULT; |
186 | nr_segs = seg; | 186 | nr_segs = seg; |
187 | count -= iv->iov_len; /* This segment is no good */ | 187 | count -= iv->iov_len; /* This segment is no good */ |
188 | break; | 188 | break; |
189 | } | 189 | } |
190 | 190 | ||
191 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ | 191 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ |
@@ -204,10 +204,14 @@ static ssize_t __gfs2_file_aio_read(struct kiocb *iocb, | |||
204 | retval = gfs2_glock_nq_m_atime(1, &gh); | 204 | retval = gfs2_glock_nq_m_atime(1, &gh); |
205 | if (retval) | 205 | if (retval) |
206 | goto out; | 206 | goto out; |
207 | 207 | if (gfs2_is_stuffed(ip)) { | |
208 | gfs2_glock_dq_m(1, &gh); | ||
209 | gfs2_holder_uninit(&gh); | ||
210 | goto fallback_to_normal; | ||
211 | } | ||
208 | size = i_size_read(inode); | 212 | size = i_size_read(inode); |
209 | if (pos < size) { | 213 | if (pos < size) { |
210 | retval = gfs2_direct_IO_read(iocb, iov, pos, nr_segs); | 214 | retval = gfs2_direct_IO_read(iocb, iov, pos, nr_segs); |
211 | if (retval > 0 && !is_sync_kiocb(iocb)) | 215 | if (retval > 0 && !is_sync_kiocb(iocb)) |
212 | retval = -EIOCBQUEUED; | 216 | retval = -EIOCBQUEUED; |
213 | if (retval > 0) | 217 | if (retval > 0) |
@@ -219,6 +223,7 @@ static ssize_t __gfs2_file_aio_read(struct kiocb *iocb, | |||
219 | goto out; | 223 | goto out; |
220 | } | 224 | } |
221 | 225 | ||
226 | fallback_to_normal: | ||
222 | retval = 0; | 227 | retval = 0; |
223 | if (count) { | 228 | if (count) { |
224 | for (seg = 0; seg < nr_segs; seg++) { | 229 | for (seg = 0; seg < nr_segs; seg++) { |