aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-10-15 09:42:35 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-01-25 03:07:11 -0500
commit51ff87bdd9f21a5d3672517b75d25ab5842d94a8 (patch)
tree7a8de5720b2a63e8d7d03a940a2b06196b2a3776
parentcc7e79b168a552152299bd8a8254dc099aacc993 (diff)
[GFS2] Clean up internal read function
As requested by Christoph, this patch cleans up GFS2's internal read function so that it no longer uses the do_generic_mapping_read function. This function is obsolete and GFS2 is the last user of it. As a side effect the internal read code gets smaller and easier to read and gfs2_readpage is split into two. One function has the locking and the other function has the rest of the logic. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Cc: Christoph Hellwig <hch@infradead.org>
-rw-r--r--fs/gfs2/inode.c1
-rw-r--r--fs/gfs2/ops_address.c151
-rw-r--r--fs/gfs2/ops_address.h3
-rw-r--r--fs/gfs2/ops_file.c45
-rw-r--r--fs/gfs2/ops_file.h24
-rw-r--r--fs/gfs2/ops_inode.h4
-rw-r--r--fs/gfs2/quota.c7
-rw-r--r--fs/gfs2/rgrp.c2
8 files changed, 111 insertions, 126 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 5f6dc32946cd..ad0fe373dca5 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -31,7 +31,6 @@
31#include "log.h" 31#include "log.h"
32#include "meta_io.h" 32#include "meta_io.h"
33#include "ops_address.h" 33#include "ops_address.h"
34#include "ops_file.h"
35#include "ops_inode.h" 34#include "ops_inode.h"
36#include "quota.h" 35#include "quota.h"
37#include "rgrp.h" 36#include "rgrp.h"
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 9679f8b9870d..9bb24b1d9c05 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -20,6 +20,7 @@
20#include <linux/swap.h> 20#include <linux/swap.h>
21#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
22#include <linux/lm_interface.h> 22#include <linux/lm_interface.h>
23#include <linux/swap.h>
23 24
24#include "gfs2.h" 25#include "gfs2.h"
25#include "incore.h" 26#include "incore.h"
@@ -32,7 +33,6 @@
32#include "quota.h" 33#include "quota.h"
33#include "trans.h" 34#include "trans.h"
34#include "rgrp.h" 35#include "rgrp.h"
35#include "ops_file.h"
36#include "super.h" 36#include "super.h"
37#include "util.h" 37#include "util.h"
38#include "glops.h" 38#include "glops.h"
@@ -231,62 +231,115 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
231 231
232 232
233/** 233/**
234 * gfs2_readpage - readpage with locking 234 * __gfs2_readpage - readpage
235 * @file: The file to read a page for. N.B. This may be NULL if we are 235 * @file: The file to read a page for
236 * reading an internal file.
237 * @page: The page to read 236 * @page: The page to read
238 * 237 *
239 * Returns: errno 238 * This is the core of gfs2's readpage. Its used by the internal file
239 * reading code as in that case we already hold the glock. Also its
240 * called by gfs2_readpage() once the required lock has been granted.
241 *
240 */ 242 */
241 243
242static int gfs2_readpage(struct file *file, struct page *page) 244static int __gfs2_readpage(void *file, struct page *page)
243{ 245{
244 struct gfs2_inode *ip = GFS2_I(page->mapping->host); 246 struct gfs2_inode *ip = GFS2_I(page->mapping->host);
245 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); 247 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
246 struct gfs2_file *gf = NULL;
247 struct gfs2_holder gh;
248 int error; 248 int error;
249 int do_unlock = 0;
250
251 if (likely(file != &gfs2_internal_file_sentinel)) {
252 if (file) {
253 gf = file->private_data;
254 if (test_bit(GFF_EXLOCK, &gf->f_flags))
255 /* gfs2_sharewrite_fault has grabbed the ip->i_gl already */
256 goto skip_lock;
257 }
258 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
259 do_unlock = 1;
260 error = gfs2_glock_nq_atime(&gh);
261 if (unlikely(error))
262 goto out_unlock;
263 }
264 249
265skip_lock:
266 if (gfs2_is_stuffed(ip)) { 250 if (gfs2_is_stuffed(ip)) {
267 error = stuffed_readpage(ip, page); 251 error = stuffed_readpage(ip, page);
268 unlock_page(page); 252 unlock_page(page);
269 } else 253 } else {
270 error = mpage_readpage(page, gfs2_get_block); 254 error = mpage_readpage(page, gfs2_get_block);
255 }
271 256
272 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 257 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
273 error = -EIO; 258 return -EIO;
274 259
275 if (do_unlock) { 260 return error;
276 gfs2_glock_dq_m(1, &gh); 261}
277 gfs2_holder_uninit(&gh); 262
263/**
264 * gfs2_readpage - read a page of a file
265 * @file: The file to read
266 * @page: The page of the file
267 *
268 * This deals with the locking required. If the GFF_EXLOCK flags is set
269 * then we already hold the glock (due to page fault) and thus we call
270 * __gfs2_readpage() directly. Otherwise we use a trylock in order to
271 * avoid the page lock / glock ordering problems returning AOP_TRUNCATED_PAGE
272 * in the event that we are unable to get the lock.
273 */
274
275static int gfs2_readpage(struct file *file, struct page *page)
276{
277 struct gfs2_inode *ip = GFS2_I(page->mapping->host);
278 struct gfs2_holder gh;
279 int error;
280
281 if (file) {
282 struct gfs2_file *gf = file->private_data;
283 if (test_bit(GFF_EXLOCK, &gf->f_flags))
284 return __gfs2_readpage(file, page);
278 } 285 }
286
287 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
288 error = gfs2_glock_nq_atime(&gh);
289 if (unlikely(error)) {
290 unlock_page(page);
291 goto out;
292 }
293 error = __gfs2_readpage(file, page);
294 gfs2_glock_dq(&gh);
279out: 295out:
280 return error; 296 gfs2_holder_uninit(&gh);
281out_unlock:
282 unlock_page(page);
283 if (error == GLR_TRYFAILED) { 297 if (error == GLR_TRYFAILED) {
284 error = AOP_TRUNCATED_PAGE;
285 yield(); 298 yield();
299 return AOP_TRUNCATED_PAGE;
286 } 300 }
287 if (do_unlock) 301 return error;
288 gfs2_holder_uninit(&gh); 302}
289 goto out; 303
304/**
305 * gfs2_internal_read - read an internal file
306 * @ip: The gfs2 inode
307 * @ra_state: The readahead state (or NULL for no readahead)
308 * @buf: The buffer to fill
309 * @pos: The file position
310 * @size: The amount to read
311 *
312 */
313
314int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
315 char *buf, loff_t *pos, unsigned size)
316{
317 struct address_space *mapping = ip->i_inode.i_mapping;
318 unsigned long index = *pos / PAGE_CACHE_SIZE;
319 unsigned offset = *pos & (PAGE_CACHE_SIZE - 1);
320 unsigned copied = 0;
321 unsigned amt;
322 struct page *page;
323 void *p;
324
325 do {
326 amt = size - copied;
327 if (offset + size > PAGE_CACHE_SIZE)
328 amt = PAGE_CACHE_SIZE - offset;
329 page = read_cache_page(mapping, index, __gfs2_readpage, NULL);
330 if (IS_ERR(page))
331 return PTR_ERR(page);
332 p = kmap_atomic(page, KM_USER0);
333 memcpy(buf + copied, p + offset, amt);
334 kunmap_atomic(p, KM_USER0);
335 mark_page_accessed(page);
336 page_cache_release(page);
337 copied += amt;
338 index++;
339 offset = 0;
340 } while(copied < size);
341 (*pos) += size;
342 return size;
290} 343}
291 344
292/** 345/**
@@ -314,21 +367,19 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
314 int ret = 0; 367 int ret = 0;
315 int do_unlock = 0; 368 int do_unlock = 0;
316 369
317 if (likely(file != &gfs2_internal_file_sentinel)) { 370 if (file) {
318 if (file) { 371 struct gfs2_file *gf = file->private_data;
319 struct gfs2_file *gf = file->private_data; 372 if (test_bit(GFF_EXLOCK, &gf->f_flags))
320 if (test_bit(GFF_EXLOCK, &gf->f_flags)) 373 goto skip_lock;
321 goto skip_lock;
322 }
323 gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
324 LM_FLAG_TRY_1CB|GL_ATIME, &gh);
325 do_unlock = 1;
326 ret = gfs2_glock_nq_atime(&gh);
327 if (ret == GLR_TRYFAILED)
328 goto out_noerror;
329 if (unlikely(ret))
330 goto out_unlock;
331 } 374 }
375 gfs2_holder_init(ip->i_gl, LM_ST_SHARED,
376 LM_FLAG_TRY_1CB|GL_ATIME, &gh);
377 do_unlock = 1;
378 ret = gfs2_glock_nq_atime(&gh);
379 if (ret == GLR_TRYFAILED)
380 goto out_noerror;
381 if (unlikely(ret))
382 goto out_unlock;
332skip_lock: 383skip_lock:
333 if (!gfs2_is_stuffed(ip)) 384 if (!gfs2_is_stuffed(ip))
334 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block); 385 ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block);
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index fa1b5b3d28b9..e8fe83fcd583 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -18,5 +18,8 @@ extern const struct address_space_operations gfs2_file_aops;
18extern int gfs2_get_block(struct inode *inode, sector_t lblock, 18extern int gfs2_get_block(struct inode *inode, sector_t lblock,
19 struct buffer_head *bh_result, int create); 19 struct buffer_head *bh_result, int create);
20extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); 20extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
21extern int gfs2_internal_read(struct gfs2_inode *ip,
22 struct file_ra_state *ra_state,
23 char *buf, loff_t *pos, unsigned size);
21 24
22#endif /* __OPS_ADDRESS_DOT_H__ */ 25#endif /* __OPS_ADDRESS_DOT_H__ */
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index bb11fd6752d3..a729c86b8be1 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -33,7 +33,6 @@
33#include "lm.h" 33#include "lm.h"
34#include "log.h" 34#include "log.h"
35#include "meta_io.h" 35#include "meta_io.h"
36#include "ops_file.h"
37#include "ops_vm.h" 36#include "ops_vm.h"
38#include "quota.h" 37#include "quota.h"
39#include "rgrp.h" 38#include "rgrp.h"
@@ -41,50 +40,6 @@
41#include "util.h" 40#include "util.h"
42#include "eaops.h" 41#include "eaops.h"
43 42
44/*
45 * Most fields left uninitialised to catch anybody who tries to
46 * use them. f_flags set to prevent file_accessed() from touching
47 * any other part of this. Its use is purely as a flag so that we
48 * know (in readpage()) whether or not do to locking.
49 */
50struct file gfs2_internal_file_sentinel = {
51 .f_flags = O_NOATIME|O_RDONLY,
52};
53
54static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
55 unsigned long offset, unsigned long size)
56{
57 char *kaddr;
58 unsigned long count = desc->count;
59
60 if (size > count)
61 size = count;
62
63 kaddr = kmap(page);
64 memcpy(desc->arg.data, kaddr + offset, size);
65 kunmap(page);
66
67 desc->count = count - size;
68 desc->written += size;
69 desc->arg.buf += size;
70 return size;
71}
72
73int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
74 char *buf, loff_t *pos, unsigned size)
75{
76 struct inode *inode = &ip->i_inode;
77 read_descriptor_t desc;
78 desc.written = 0;
79 desc.arg.data = buf;
80 desc.count = size;
81 desc.error = 0;
82 do_generic_mapping_read(inode->i_mapping, ra_state,
83 &gfs2_internal_file_sentinel, pos, &desc,
84 gfs2_read_actor);
85 return desc.written ? desc.written : desc.error;
86}
87
88/** 43/**
89 * gfs2_llseek - seek to a location in a file 44 * gfs2_llseek - seek to a location in a file
90 * @file: the file 45 * @file: the file
diff --git a/fs/gfs2/ops_file.h b/fs/gfs2/ops_file.h
deleted file mode 100644
index 7e5d8ec9c846..000000000000
--- a/fs/gfs2/ops_file.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License version 2.
8 */
9
10#ifndef __OPS_FILE_DOT_H__
11#define __OPS_FILE_DOT_H__
12
13#include <linux/fs.h>
14struct gfs2_inode;
15
16extern struct file gfs2_internal_file_sentinel;
17extern int gfs2_internal_read(struct gfs2_inode *ip,
18 struct file_ra_state *ra_state,
19 char *buf, loff_t *pos, unsigned size);
20extern void gfs2_set_inode_flags(struct inode *inode);
21extern const struct file_operations gfs2_file_fops;
22extern const struct file_operations gfs2_dir_fops;
23
24#endif /* __OPS_FILE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
index 34f0caac1a03..edb519cb05ee 100644
--- a/fs/gfs2/ops_inode.h
+++ b/fs/gfs2/ops_inode.h
@@ -16,5 +16,9 @@ extern const struct inode_operations gfs2_file_iops;
16extern const struct inode_operations gfs2_dir_iops; 16extern const struct inode_operations gfs2_dir_iops;
17extern const struct inode_operations gfs2_symlink_iops; 17extern const struct inode_operations gfs2_symlink_iops;
18extern const struct inode_operations gfs2_dev_iops; 18extern const struct inode_operations gfs2_dev_iops;
19extern const struct file_operations gfs2_file_fops;
20extern const struct file_operations gfs2_dir_fops;
21
22extern void gfs2_set_inode_flags(struct inode *inode);
19 23
20#endif /* __OPS_INODE_DOT_H__ */ 24#endif /* __OPS_INODE_DOT_H__ */
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index addb51e0f135..4996f0ef3007 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -59,7 +59,6 @@
59#include "super.h" 59#include "super.h"
60#include "trans.h" 60#include "trans.h"
61#include "inode.h" 61#include "inode.h"
62#include "ops_file.h"
63#include "ops_address.h" 62#include "ops_address.h"
64#include "util.h" 63#include "util.h"
65 64
@@ -793,11 +792,9 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
793 struct gfs2_holder i_gh; 792 struct gfs2_holder i_gh;
794 struct gfs2_quota_host q; 793 struct gfs2_quota_host q;
795 char buf[sizeof(struct gfs2_quota)]; 794 char buf[sizeof(struct gfs2_quota)];
796 struct file_ra_state ra_state;
797 int error; 795 int error;
798 struct gfs2_quota_lvb *qlvb; 796 struct gfs2_quota_lvb *qlvb;
799 797
800 file_ra_state_init(&ra_state, sdp->sd_quota_inode->i_mapping);
801restart: 798restart:
802 error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); 799 error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh);
803 if (error) 800 if (error)
@@ -820,8 +817,8 @@ restart:
820 817
821 memset(buf, 0, sizeof(struct gfs2_quota)); 818 memset(buf, 0, sizeof(struct gfs2_quota));
822 pos = qd2offset(qd); 819 pos = qd2offset(qd);
823 error = gfs2_internal_read(ip, &ra_state, buf, 820 error = gfs2_internal_read(ip, NULL, buf, &pos,
824 &pos, sizeof(struct gfs2_quota)); 821 sizeof(struct gfs2_quota));
825 if (error < 0) 822 if (error < 0)
826 goto fail_gunlock; 823 goto fail_gunlock;
827 824
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 708c287e1d0e..09848aac45f6 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -25,10 +25,10 @@
25#include "rgrp.h" 25#include "rgrp.h"
26#include "super.h" 26#include "super.h"
27#include "trans.h" 27#include "trans.h"
28#include "ops_file.h"
29#include "util.h" 28#include "util.h"
30#include "log.h" 29#include "log.h"
31#include "inode.h" 30#include "inode.h"
31#include "ops_address.h"
32 32
33#define BFITNOENT ((u32)~0) 33#define BFITNOENT ((u32)~0)
34#define NO_BLOCK ((u64)~0) 34#define NO_BLOCK ((u64)~0)