aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c260
1 files changed, 169 insertions, 91 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index d611b2ad2e97..b14357e89421 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -20,13 +20,13 @@
20#include "bmap.h" 20#include "bmap.h"
21#include "glock.h" 21#include "glock.h"
22#include "inode.h" 22#include "inode.h"
23#include "jdata.h"
24#include "log.h" 23#include "log.h"
25#include "meta_io.h" 24#include "meta_io.h"
26#include "ops_address.h" 25#include "ops_address.h"
27#include "page.h" 26#include "page.h"
28#include "quota.h" 27#include "quota.h"
29#include "trans.h" 28#include "trans.h"
29#include "rgrp.h"
30 30
31/** 31/**
32 * gfs2_get_block - Fills in a buffer head with details about a block 32 * gfs2_get_block - Fills in a buffer head with details about a block
@@ -149,33 +149,55 @@ static int get_blocks_noalloc(struct inode *inode, sector_t lblock,
149 * 149 *
150 * Returns: errno 150 * Returns: errno
151 * 151 *
152 * Use Linux VFS block_write_full_page() to write one page, 152 * Some of this is copied from block_write_full_page() although we still
153 * using GFS2's get_block_noalloc to find which blocks to write. 153 * call it to do most of the work.
154 */ 154 */
155 155
156static int gfs2_writepage(struct page *page, struct writeback_control *wbc) 156static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
157{ 157{
158 struct inode *inode = page->mapping->host;
158 struct gfs2_inode *ip = get_v2ip(page->mapping->host); 159 struct gfs2_inode *ip = get_v2ip(page->mapping->host);
159 struct gfs2_sbd *sdp = ip->i_sbd; 160 struct gfs2_sbd *sdp = ip->i_sbd;
161 loff_t i_size = i_size_read(inode);
162 pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
163 unsigned offset;
160 int error; 164 int error;
165 int done_trans = 0;
161 166
162 atomic_inc(&sdp->sd_ops_address); 167 atomic_inc(&sdp->sd_ops_address);
163
164 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) { 168 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) {
165 unlock_page(page); 169 unlock_page(page);
166 return -EIO; 170 return -EIO;
167 } 171 }
168 if (get_transaction) { 172 if (get_transaction)
169 redirty_page_for_writepage(wbc, page); 173 goto out_ignore;
174
175 /* Is the page fully outside i_size? (truncate in progress) */
176 offset = i_size & (PAGE_CACHE_SIZE-1);
177 if (page->index >= end_index+1 || !offset) {
178 page->mapping->a_ops->invalidatepage(page, 0);
170 unlock_page(page); 179 unlock_page(page);
171 return 0; 180 return 0; /* don't care */
172 } 181 }
173 182
174 error = block_write_full_page(page, get_block_noalloc, wbc); 183 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) {
184 error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
185 if (error)
186 goto out_ignore;
187 gfs2_page_add_databufs(ip, page, 0, sdp->sd_vfs->s_blocksize-1);
188 done_trans = 1;
189 }
175 190
191 error = block_write_full_page(page, get_block_noalloc, wbc);
192 if (done_trans)
193 gfs2_trans_end(sdp);
176 gfs2_meta_cache_flush(ip); 194 gfs2_meta_cache_flush(ip);
177
178 return error; 195 return error;
196
197out_ignore:
198 redirty_page_for_writepage(wbc, page);
199 unlock_page(page);
200 return 0;
179} 201}
180 202
181/** 203/**
@@ -227,40 +249,9 @@ static int zero_readpage(struct page *page)
227} 249}
228 250
229/** 251/**
230 * jdata_readpage - readpage that goes through gfs2_jdata_read_mem()
231 * @ip:
232 * @page: The page to read
233 *
234 * Returns: errno
235 */
236
237static int jdata_readpage(struct gfs2_inode *ip, struct page *page)
238{
239 void *kaddr;
240 int ret;
241
242 kaddr = kmap(page);
243
244 ret = gfs2_jdata_read_mem(ip, kaddr,
245 (uint64_t)page->index << PAGE_CACHE_SHIFT,
246 PAGE_CACHE_SIZE);
247 if (ret >= 0) {
248 if (ret < PAGE_CACHE_SIZE)
249 memset(kaddr + ret, 0, PAGE_CACHE_SIZE - ret);
250 SetPageUptodate(page);
251 ret = 0;
252 }
253
254 kunmap(page);
255
256 unlock_page(page);
257
258 return ret;
259}
260
261/**
262 * gfs2_readpage - readpage with locking 252 * gfs2_readpage - readpage with locking
263 * @file: The file to read a page for 253 * @file: The file to read a page for. N.B. This may be NULL if we are
254 * reading an internal file.
264 * @page: The page to read 255 * @page: The page to read
265 * 256 *
266 * Returns: errno 257 * Returns: errno
@@ -270,31 +261,35 @@ static int gfs2_readpage(struct file *file, struct page *page)
270{ 261{
271 struct gfs2_inode *ip = get_v2ip(page->mapping->host); 262 struct gfs2_inode *ip = get_v2ip(page->mapping->host);
272 struct gfs2_sbd *sdp = ip->i_sbd; 263 struct gfs2_sbd *sdp = ip->i_sbd;
264 struct gfs2_holder gh;
273 int error; 265 int error;
274 266
275 atomic_inc(&sdp->sd_ops_address); 267 atomic_inc(&sdp->sd_ops_address);
276 268
277 if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl))) { 269 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
278 unlock_page(page); 270 error = gfs2_glock_nq_m_atime(1, &gh);
279 return -EOPNOTSUPP; 271 if (error)
280 } 272 goto out_unlock;
281 273
282 if (!gfs2_is_jdata(ip)) { 274 if (gfs2_is_stuffed(ip)) {
283 if (gfs2_is_stuffed(ip)) { 275 if (!page->index) {
284 if (!page->index) { 276 error = stuffed_readpage(ip, page);
285 error = stuffed_readpage(ip, page); 277 unlock_page(page);
286 unlock_page(page);
287 } else
288 error = zero_readpage(page);
289 } else 278 } else
290 error = mpage_readpage(page, gfs2_get_block); 279 error = zero_readpage(page);
291 } else 280 } else
292 error = jdata_readpage(ip, page); 281 error = mpage_readpage(page, gfs2_get_block);
293 282
294 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 283 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
295 error = -EIO; 284 error = -EIO;
296 285
286 gfs2_glock_dq_m(1, &gh);
287 gfs2_holder_uninit(&gh);
288out:
297 return error; 289 return error;
290out_unlock:
291 unlock_page(page);
292 goto out;
298} 293}
299 294
300/** 295/**
@@ -312,28 +307,82 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
312{ 307{
313 struct gfs2_inode *ip = get_v2ip(page->mapping->host); 308 struct gfs2_inode *ip = get_v2ip(page->mapping->host);
314 struct gfs2_sbd *sdp = ip->i_sbd; 309 struct gfs2_sbd *sdp = ip->i_sbd;
310 unsigned int data_blocks, ind_blocks, rblocks;
311 int alloc_required;
315 int error = 0; 312 int error = 0;
313 loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + from;
314 loff_t end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
315 struct gfs2_alloc *al;
316 316
317 atomic_inc(&sdp->sd_ops_address); 317 atomic_inc(&sdp->sd_ops_address);
318 318
319 if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl))) 319 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh);
320 return -EOPNOTSUPP; 320 error = gfs2_glock_nq_m_atime(1, &ip->i_gh);
321 if (error)
322 goto out_uninit;
321 323
322 if (gfs2_is_stuffed(ip)) { 324 gfs2_write_calc_reserv(ip, to - from, &data_blocks, &ind_blocks);
323 uint64_t file_size; 325
324 file_size = ((uint64_t)page->index << PAGE_CACHE_SHIFT) + to; 326 error = gfs2_write_alloc_required(ip, pos, from - to, &alloc_required);
327 if (error)
328 goto out_unlock;
325 329
326 if (file_size > sdp->sd_sb.sb_bsize - 330
327 sizeof(struct gfs2_dinode)) { 331 if (alloc_required) {
328 error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, 332 al = gfs2_alloc_get(ip);
329 page); 333
330 if (!error) 334 error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
331 error = block_prepare_write(page, from, to, 335 if (error)
332 gfs2_get_block); 336 goto out_alloc_put;
333 } else if (!PageUptodate(page)) 337
338 error = gfs2_quota_check(ip, ip->i_di.di_uid, ip->i_di.di_gid);
339 if (error)
340 goto out_qunlock;
341
342 al->al_requested = data_blocks + ind_blocks;
343 error = gfs2_inplace_reserve(ip);
344 if (error)
345 goto out_qunlock;
346 }
347
348 rblocks = RES_DINODE + ind_blocks;
349 if (gfs2_is_jdata(ip))
350 rblocks += data_blocks ? data_blocks : 1;
351 if (ind_blocks || data_blocks)
352 rblocks += RES_STATFS + RES_QUOTA;
353
354 error = gfs2_trans_begin(sdp, rblocks, 0);
355 if (error)
356 goto out;
357
358 if (gfs2_is_stuffed(ip)) {
359 if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
360 error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, page);
361 if (error)
362 goto out;
363 } else if (!PageUptodate(page)) {
334 error = stuffed_readpage(ip, page); 364 error = stuffed_readpage(ip, page);
335 } else 365 goto out;
336 error = block_prepare_write(page, from, to, gfs2_get_block); 366 }
367 }
368
369 error = block_prepare_write(page, from, to, gfs2_get_block);
370
371out:
372 if (error) {
373 gfs2_trans_end(sdp);
374 if (alloc_required) {
375 gfs2_inplace_release(ip);
376out_qunlock:
377 gfs2_quota_unlock(ip);
378out_alloc_put:
379 gfs2_alloc_put(ip);
380 }
381out_unlock:
382 gfs2_glock_dq_m(1, &ip->i_gh);
383out_uninit:
384 gfs2_holder_uninit(&ip->i_gh);
385 }
337 386
338 return error; 387 return error;
339} 388}
@@ -354,48 +403,73 @@ static int gfs2_commit_write(struct file *file, struct page *page,
354 struct inode *inode = page->mapping->host; 403 struct inode *inode = page->mapping->host;
355 struct gfs2_inode *ip = get_v2ip(inode); 404 struct gfs2_inode *ip = get_v2ip(inode);
356 struct gfs2_sbd *sdp = ip->i_sbd; 405 struct gfs2_sbd *sdp = ip->i_sbd;
357 int error; 406 int error = -EOPNOTSUPP;
407 struct buffer_head *dibh;
408 struct gfs2_alloc *al = &ip->i_alloc;;
358 409
359 atomic_inc(&sdp->sd_ops_address); 410 atomic_inc(&sdp->sd_ops_address);
360 411
412
413 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)))
414 goto fail_nounlock;
415
416 error = gfs2_meta_inode_buffer(ip, &dibh);
417 if (error)
418 goto fail_endtrans;
419
420 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
421
361 if (gfs2_is_stuffed(ip)) { 422 if (gfs2_is_stuffed(ip)) {
362 struct buffer_head *dibh;
363 uint64_t file_size; 423 uint64_t file_size;
364 void *kaddr; 424 void *kaddr;
365 425
366 file_size = ((uint64_t)page->index << PAGE_CACHE_SHIFT) + to; 426 file_size = ((uint64_t)page->index << PAGE_CACHE_SHIFT) + to;
367 427
368 error = gfs2_meta_inode_buffer(ip, &dibh); 428 kaddr = kmap_atomic(page, KM_USER0);
369 if (error)
370 goto fail;
371
372 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
373
374 kaddr = kmap(page);
375 memcpy(dibh->b_data + sizeof(struct gfs2_dinode) + from, 429 memcpy(dibh->b_data + sizeof(struct gfs2_dinode) + from,
376 (char *)kaddr + from, 430 (char *)kaddr + from, to - from);
377 to - from); 431 kunmap_atomic(page, KM_USER0);
378 kunmap(page);
379
380 brelse(dibh);
381 432
382 SetPageUptodate(page); 433 SetPageUptodate(page);
383 434
384 if (inode->i_size < file_size) 435 if (inode->i_size < file_size)
385 i_size_write(inode, file_size); 436 i_size_write(inode, file_size);
386 } else { 437 } else {
387 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED) 438 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
388 gfs2_page_add_databufs(ip, page, from, to); 439 gfs2_page_add_databufs(ip, page, from, to);
389 error = generic_commit_write(file, page, from, to); 440 error = generic_commit_write(file, page, from, to);
390 if (error) 441 if (error)
391 goto fail; 442 goto fail;
392 } 443 }
393 444
445 if (ip->i_di.di_size < inode->i_size)
446 ip->i_di.di_size = inode->i_size;
447
448 gfs2_dinode_out(&ip->i_di, dibh->b_data);
449 brelse(dibh);
450 gfs2_trans_end(sdp);
451 if (al->al_requested) {
452 gfs2_inplace_release(ip);
453 gfs2_quota_unlock(ip);
454 gfs2_alloc_put(ip);
455 }
456 gfs2_glock_dq_m(1, &ip->i_gh);
457 gfs2_holder_uninit(&ip->i_gh);
394 return 0; 458 return 0;
395 459
396 fail: 460fail:
461 brelse(dibh);
462fail_endtrans:
463 gfs2_trans_end(sdp);
464 if (al->al_requested) {
465 gfs2_inplace_release(ip);
466 gfs2_quota_unlock(ip);
467 gfs2_alloc_put(ip);
468 }
469 gfs2_glock_dq_m(1, &ip->i_gh);
470 gfs2_holder_uninit(&ip->i_gh);
471fail_nounlock:
397 ClearPageUptodate(page); 472 ClearPageUptodate(page);
398
399 return error; 473 return error;
400} 474}
401 475
@@ -492,12 +566,16 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *io
492 566
493 atomic_inc(&sdp->sd_ops_address); 567 atomic_inc(&sdp->sd_ops_address);
494 568
495 if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)) || 569 if (gfs2_is_jdata(ip))
496 gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
497 return -EINVAL; 570 return -EINVAL;
498 571
499 if (rw == WRITE && !get_transaction) 572 if (rw == WRITE) {
500 gb = get_blocks_noalloc; 573 return -EOPNOTSUPP; /* for now */
574 } else {
575 if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)) ||
576 gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
577 return -EINVAL;
578 }
501 579
502 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 580 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
503 offset, nr_segs, gb, NULL); 581 offset, nr_segs, gb, NULL);