diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:41:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:41:18 -0400 |
commit | c4eb1b07303ad9e00aba842aa90d5521293ac857 (patch) | |
tree | 114afde9e414e8bc1e069ea1e5226103c53ac305 | |
parent | 9e239bb93914e1c832d54161c7f8f398d0c914ab (diff) | |
parent | a01aedfe21637c965a7046271fedfdd681eba646 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Pull GFS2 updates from Steven Whitehouse:
"There are a few bug fixes for various, mostly very minor corner cases,
plus some interesting new features.
The new features include atomic_open whose main benefit will be the
reduction in locking overhead in case of combined lookup/create and
open operations, sorting the log buffer lists by block number to
improve the efficiency of AIL writeback, and aggressively issuing
revokes in gfs2_log_flush to reduce overhead when dropping glocks."
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
GFS2: Reserve journal space for quota change in do_grow
GFS2: Fix fstrim boundary conditions
GFS2: fix warning message
GFS2: aggressively issue revokes in gfs2_log_flush
GFS2: fix regression in dir_double_exhash
GFS2: Add atomic_open support
GFS2: Only do one directory search on create
GFS2: fix error propagation in init_threads()
GFS2: Remove no-op wrapper function
GFS2: Cocci spatch "ptr_ret.spatch"
GFS2: Eliminate gfs2_rg_lops
GFS2: Sort buffer lists by inplace block number
-rw-r--r-- | fs/dcache.c | 11 | ||||
-rw-r--r-- | fs/gfs2/bmap.c | 4 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 26 | ||||
-rw-r--r-- | fs/gfs2/dir.h | 3 | ||||
-rw-r--r-- | fs/gfs2/file.c | 69 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 8 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 150 | ||||
-rw-r--r-- | fs/gfs2/inode.h | 1 | ||||
-rw-r--r-- | fs/gfs2/log.c | 78 | ||||
-rw-r--r-- | fs/gfs2/log.h | 2 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 22 | ||||
-rw-r--r-- | fs/gfs2/lops.h | 1 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 4 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 8 | ||||
-rw-r--r-- | fs/gfs2/quota.c | 7 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 14 | ||||
-rw-r--r-- | fs/gfs2/trans.c | 9 |
17 files changed, 291 insertions, 126 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index f09b9085f7d8..5a23073138df 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1612,6 +1612,10 @@ EXPORT_SYMBOL(d_obtain_alias); | |||
1612 | * If a dentry was found and moved, then it is returned. Otherwise NULL | 1612 | * If a dentry was found and moved, then it is returned. Otherwise NULL |
1613 | * is returned. This matches the expected return value of ->lookup. | 1613 | * is returned. This matches the expected return value of ->lookup. |
1614 | * | 1614 | * |
1615 | * Cluster filesystems may call this function with a negative, hashed dentry. | ||
1616 | * In that case, we know that the inode will be a regular file, and also this | ||
1617 | * will only occur during atomic_open. So we need to check for the dentry | ||
1618 | * being already hashed only in the final case. | ||
1615 | */ | 1619 | */ |
1616 | struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | 1620 | struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) |
1617 | { | 1621 | { |
@@ -1636,8 +1640,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1636 | security_d_instantiate(dentry, inode); | 1640 | security_d_instantiate(dentry, inode); |
1637 | d_rehash(dentry); | 1641 | d_rehash(dentry); |
1638 | } | 1642 | } |
1639 | } else | 1643 | } else { |
1640 | d_add(dentry, inode); | 1644 | d_instantiate(dentry, inode); |
1645 | if (d_unhashed(dentry)) | ||
1646 | d_rehash(dentry); | ||
1647 | } | ||
1641 | return new; | 1648 | return new; |
1642 | } | 1649 | } |
1643 | EXPORT_SYMBOL(d_splice_alias); | 1650 | EXPORT_SYMBOL(d_splice_alias); |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 93b5809c20bb..5e2f56fccf6b 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -1232,7 +1232,9 @@ static int do_grow(struct inode *inode, u64 size) | |||
1232 | unstuff = 1; | 1232 | unstuff = 1; |
1233 | } | 1233 | } |
1234 | 1234 | ||
1235 | error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0); | 1235 | error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT + |
1236 | (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF ? | ||
1237 | 0 : RES_QUOTA), 0); | ||
1236 | if (error) | 1238 | if (error) |
1237 | goto do_grow_release; | 1239 | goto do_grow_release; |
1238 | 1240 | ||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index e0449c10286a..0cb4c1557f20 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1125,13 +1125,14 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
1125 | if (IS_ERR(hc)) | 1125 | if (IS_ERR(hc)) |
1126 | return PTR_ERR(hc); | 1126 | return PTR_ERR(hc); |
1127 | 1127 | ||
1128 | h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN); | 1128 | hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN); |
1129 | if (hc2 == NULL) | 1129 | if (hc2 == NULL) |
1130 | hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL); | 1130 | hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL); |
1131 | 1131 | ||
1132 | if (!hc2) | 1132 | if (!hc2) |
1133 | return -ENOMEM; | 1133 | return -ENOMEM; |
1134 | 1134 | ||
1135 | h = hc2; | ||
1135 | error = gfs2_meta_inode_buffer(dip, &dibh); | 1136 | error = gfs2_meta_inode_buffer(dip, &dibh); |
1136 | if (error) | 1137 | if (error) |
1137 | goto out_kfree; | 1138 | goto out_kfree; |
@@ -1547,9 +1548,9 @@ out: | |||
1547 | 1548 | ||
1548 | /** | 1549 | /** |
1549 | * gfs2_dir_search - Search a directory | 1550 | * gfs2_dir_search - Search a directory |
1550 | * @dip: The GFS2 inode | 1551 | * @dip: The GFS2 dir inode |
1551 | * @filename: | 1552 | * @name: The name we are looking up |
1552 | * @inode: | 1553 | * @fail_on_exist: Fail if the name exists rather than looking it up |
1553 | * | 1554 | * |
1554 | * This routine searches a directory for a file or another directory. | 1555 | * This routine searches a directory for a file or another directory. |
1555 | * Assumes a glock is held on dip. | 1556 | * Assumes a glock is held on dip. |
@@ -1557,22 +1558,25 @@ out: | |||
1557 | * Returns: errno | 1558 | * Returns: errno |
1558 | */ | 1559 | */ |
1559 | 1560 | ||
1560 | struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) | 1561 | struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name, |
1562 | bool fail_on_exist) | ||
1561 | { | 1563 | { |
1562 | struct buffer_head *bh; | 1564 | struct buffer_head *bh; |
1563 | struct gfs2_dirent *dent; | 1565 | struct gfs2_dirent *dent; |
1564 | struct inode *inode; | 1566 | u64 addr, formal_ino; |
1567 | u16 dtype; | ||
1565 | 1568 | ||
1566 | dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); | 1569 | dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh); |
1567 | if (dent) { | 1570 | if (dent) { |
1568 | if (IS_ERR(dent)) | 1571 | if (IS_ERR(dent)) |
1569 | return ERR_CAST(dent); | 1572 | return ERR_CAST(dent); |
1570 | inode = gfs2_inode_lookup(dir->i_sb, | 1573 | dtype = be16_to_cpu(dent->de_type); |
1571 | be16_to_cpu(dent->de_type), | 1574 | addr = be64_to_cpu(dent->de_inum.no_addr); |
1572 | be64_to_cpu(dent->de_inum.no_addr), | 1575 | formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino); |
1573 | be64_to_cpu(dent->de_inum.no_formal_ino), 0); | ||
1574 | brelse(bh); | 1576 | brelse(bh); |
1575 | return inode; | 1577 | if (fail_on_exist) |
1578 | return ERR_PTR(-EEXIST); | ||
1579 | return gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0); | ||
1576 | } | 1580 | } |
1577 | return ERR_PTR(-ENOENT); | 1581 | return ERR_PTR(-ENOENT); |
1578 | } | 1582 | } |
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h index ba9000bc1397..4f03bbd1873f 100644 --- a/fs/gfs2/dir.h +++ b/fs/gfs2/dir.h | |||
@@ -18,7 +18,8 @@ struct gfs2_inode; | |||
18 | struct gfs2_inum; | 18 | struct gfs2_inum; |
19 | 19 | ||
20 | extern struct inode *gfs2_dir_search(struct inode *dir, | 20 | extern struct inode *gfs2_dir_search(struct inode *dir, |
21 | const struct qstr *filename); | 21 | const struct qstr *filename, |
22 | bool fail_on_exist); | ||
22 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, | 23 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, |
23 | const struct gfs2_inode *ip); | 24 | const struct gfs2_inode *ip); |
24 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 25 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b3333371aebb..f99f9e8a325f 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -531,21 +531,30 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) | |||
531 | } | 531 | } |
532 | 532 | ||
533 | /** | 533 | /** |
534 | * gfs2_open - open a file | 534 | * gfs2_open_common - This is common to open and atomic_open |
535 | * @inode: the inode to open | 535 | * @inode: The inode being opened |
536 | * @file: the struct file for this opening | 536 | * @file: The file being opened |
537 | * | 537 | * |
538 | * Returns: errno | 538 | * This maybe called under a glock or not depending upon how it has |
539 | * been called. We must always be called under a glock for regular | ||
540 | * files, however. For other file types, it does not matter whether | ||
541 | * we hold the glock or not. | ||
542 | * | ||
543 | * Returns: Error code or 0 for success | ||
539 | */ | 544 | */ |
540 | 545 | ||
541 | static int gfs2_open(struct inode *inode, struct file *file) | 546 | int gfs2_open_common(struct inode *inode, struct file *file) |
542 | { | 547 | { |
543 | struct gfs2_inode *ip = GFS2_I(inode); | ||
544 | struct gfs2_holder i_gh; | ||
545 | struct gfs2_file *fp; | 548 | struct gfs2_file *fp; |
546 | int error; | 549 | int ret; |
547 | 550 | ||
548 | fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL); | 551 | if (S_ISREG(inode->i_mode)) { |
552 | ret = generic_file_open(inode, file); | ||
553 | if (ret) | ||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | fp = kzalloc(sizeof(struct gfs2_file), GFP_NOFS); | ||
549 | if (!fp) | 558 | if (!fp) |
550 | return -ENOMEM; | 559 | return -ENOMEM; |
551 | 560 | ||
@@ -553,29 +562,43 @@ static int gfs2_open(struct inode *inode, struct file *file) | |||
553 | 562 | ||
554 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); | 563 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); |
555 | file->private_data = fp; | 564 | file->private_data = fp; |
565 | return 0; | ||
566 | } | ||
567 | |||
568 | /** | ||
569 | * gfs2_open - open a file | ||
570 | * @inode: the inode to open | ||
571 | * @file: the struct file for this opening | ||
572 | * | ||
573 | * After atomic_open, this function is only used for opening files | ||
574 | * which are already cached. We must still get the glock for regular | ||
575 | * files to ensure that we have the file size uptodate for the large | ||
576 | * file check which is in the common code. That is only an issue for | ||
577 | * regular files though. | ||
578 | * | ||
579 | * Returns: errno | ||
580 | */ | ||
581 | |||
582 | static int gfs2_open(struct inode *inode, struct file *file) | ||
583 | { | ||
584 | struct gfs2_inode *ip = GFS2_I(inode); | ||
585 | struct gfs2_holder i_gh; | ||
586 | int error; | ||
587 | bool need_unlock = false; | ||
556 | 588 | ||
557 | if (S_ISREG(ip->i_inode.i_mode)) { | 589 | if (S_ISREG(ip->i_inode.i_mode)) { |
558 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, | 590 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, |
559 | &i_gh); | 591 | &i_gh); |
560 | if (error) | 592 | if (error) |
561 | goto fail; | 593 | return error; |
594 | need_unlock = true; | ||
595 | } | ||
562 | 596 | ||
563 | if (!(file->f_flags & O_LARGEFILE) && | 597 | error = gfs2_open_common(inode, file); |
564 | i_size_read(inode) > MAX_NON_LFS) { | ||
565 | error = -EOVERFLOW; | ||
566 | goto fail_gunlock; | ||
567 | } | ||
568 | 598 | ||
599 | if (need_unlock) | ||
569 | gfs2_glock_dq_uninit(&i_gh); | 600 | gfs2_glock_dq_uninit(&i_gh); |
570 | } | ||
571 | |||
572 | return 0; | ||
573 | 601 | ||
574 | fail_gunlock: | ||
575 | gfs2_glock_dq_uninit(&i_gh); | ||
576 | fail: | ||
577 | file->private_data = NULL; | ||
578 | kfree(fp); | ||
579 | return error; | 602 | return error; |
580 | } | 603 | } |
581 | 604 | ||
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index c66e99c97571..5f2e5224c51c 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -54,7 +54,6 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
54 | struct gfs2_bufdata *bd, *tmp; | 54 | struct gfs2_bufdata *bd, *tmp; |
55 | struct buffer_head *bh; | 55 | struct buffer_head *bh; |
56 | const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock); | 56 | const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock); |
57 | sector_t blocknr; | ||
58 | 57 | ||
59 | gfs2_log_lock(sdp); | 58 | gfs2_log_lock(sdp); |
60 | spin_lock(&sdp->sd_ail_lock); | 59 | spin_lock(&sdp->sd_ail_lock); |
@@ -65,13 +64,6 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) | |||
65 | continue; | 64 | continue; |
66 | gfs2_ail_error(gl, bh); | 65 | gfs2_ail_error(gl, bh); |
67 | } | 66 | } |
68 | blocknr = bh->b_blocknr; | ||
69 | bh->b_private = NULL; | ||
70 | gfs2_remove_from_ail(bd); /* drops ref on bh */ | ||
71 | |||
72 | bd->bd_bh = NULL; | ||
73 | bd->bd_blkno = blocknr; | ||
74 | |||
75 | gfs2_trans_add_revoke(sdp, bd); | 67 | gfs2_trans_add_revoke(sdp, bd); |
76 | } | 68 | } |
77 | GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); | 69 | GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 62b484e4a9e4..bbb2715171cd 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -313,7 +313,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
313 | goto out; | 313 | goto out; |
314 | } | 314 | } |
315 | 315 | ||
316 | inode = gfs2_dir_search(dir, name); | 316 | inode = gfs2_dir_search(dir, name, false); |
317 | if (IS_ERR(inode)) | 317 | if (IS_ERR(inode)) |
318 | error = PTR_ERR(inode); | 318 | error = PTR_ERR(inode); |
319 | out: | 319 | out: |
@@ -346,17 +346,6 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
346 | if (!dip->i_inode.i_nlink) | 346 | if (!dip->i_inode.i_nlink) |
347 | return -ENOENT; | 347 | return -ENOENT; |
348 | 348 | ||
349 | error = gfs2_dir_check(&dip->i_inode, name, NULL); | ||
350 | switch (error) { | ||
351 | case -ENOENT: | ||
352 | error = 0; | ||
353 | break; | ||
354 | case 0: | ||
355 | return -EEXIST; | ||
356 | default: | ||
357 | return error; | ||
358 | } | ||
359 | |||
360 | if (dip->i_entries == (u32)-1) | 349 | if (dip->i_entries == (u32)-1) |
361 | return -EFBIG; | 350 | return -EFBIG; |
362 | if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1) | 351 | if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1) |
@@ -546,6 +535,7 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, | |||
546 | * gfs2_create_inode - Create a new inode | 535 | * gfs2_create_inode - Create a new inode |
547 | * @dir: The parent directory | 536 | * @dir: The parent directory |
548 | * @dentry: The new dentry | 537 | * @dentry: The new dentry |
538 | * @file: If non-NULL, the file which is being opened | ||
549 | * @mode: The permissions on the new inode | 539 | * @mode: The permissions on the new inode |
550 | * @dev: For device nodes, this is the device number | 540 | * @dev: For device nodes, this is the device number |
551 | * @symname: For symlinks, this is the link destination | 541 | * @symname: For symlinks, this is the link destination |
@@ -555,8 +545,9 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, | |||
555 | */ | 545 | */ |
556 | 546 | ||
557 | static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | 547 | static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, |
548 | struct file *file, | ||
558 | umode_t mode, dev_t dev, const char *symname, | 549 | umode_t mode, dev_t dev, const char *symname, |
559 | unsigned int size, int excl) | 550 | unsigned int size, int excl, int *opened) |
560 | { | 551 | { |
561 | const struct qstr *name = &dentry->d_name; | 552 | const struct qstr *name = &dentry->d_name; |
562 | struct gfs2_holder ghs[2]; | 553 | struct gfs2_holder ghs[2]; |
@@ -564,6 +555,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
564 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | 555 | struct gfs2_inode *dip = GFS2_I(dir), *ip; |
565 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 556 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
566 | struct gfs2_glock *io_gl; | 557 | struct gfs2_glock *io_gl; |
558 | struct dentry *d; | ||
567 | int error; | 559 | int error; |
568 | u32 aflags = 0; | 560 | u32 aflags = 0; |
569 | int arq; | 561 | int arq; |
@@ -584,15 +576,30 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
584 | goto fail; | 576 | goto fail; |
585 | 577 | ||
586 | error = create_ok(dip, name, mode); | 578 | error = create_ok(dip, name, mode); |
587 | if ((error == -EEXIST) && S_ISREG(mode) && !excl) { | ||
588 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | ||
589 | gfs2_glock_dq_uninit(ghs); | ||
590 | d_instantiate(dentry, inode); | ||
591 | return IS_ERR(inode) ? PTR_ERR(inode) : 0; | ||
592 | } | ||
593 | if (error) | 579 | if (error) |
594 | goto fail_gunlock; | 580 | goto fail_gunlock; |
595 | 581 | ||
582 | inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); | ||
583 | error = PTR_ERR(inode); | ||
584 | if (!IS_ERR(inode)) { | ||
585 | d = d_splice_alias(inode, dentry); | ||
586 | error = 0; | ||
587 | if (file && !IS_ERR(d)) { | ||
588 | if (d == NULL) | ||
589 | d = dentry; | ||
590 | if (S_ISREG(inode->i_mode)) | ||
591 | error = finish_open(file, d, gfs2_open_common, opened); | ||
592 | else | ||
593 | error = finish_no_open(file, d); | ||
594 | } | ||
595 | gfs2_glock_dq_uninit(ghs); | ||
596 | if (IS_ERR(d)) | ||
597 | return PTR_RET(d); | ||
598 | return error; | ||
599 | } else if (error != -ENOENT) { | ||
600 | goto fail_gunlock; | ||
601 | } | ||
602 | |||
596 | arq = error = gfs2_diradd_alloc_required(dir, name); | 603 | arq = error = gfs2_diradd_alloc_required(dir, name); |
597 | if (error < 0) | 604 | if (error < 0) |
598 | goto fail_gunlock; | 605 | goto fail_gunlock; |
@@ -686,10 +693,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
686 | goto fail_gunlock3; | 693 | goto fail_gunlock3; |
687 | 694 | ||
688 | mark_inode_dirty(inode); | 695 | mark_inode_dirty(inode); |
696 | d_instantiate(dentry, inode); | ||
697 | if (file) | ||
698 | error = finish_open(file, dentry, gfs2_open_common, opened); | ||
689 | gfs2_glock_dq_uninit(ghs); | 699 | gfs2_glock_dq_uninit(ghs); |
690 | gfs2_glock_dq_uninit(ghs + 1); | 700 | gfs2_glock_dq_uninit(ghs + 1); |
691 | d_instantiate(dentry, inode); | 701 | return error; |
692 | return 0; | ||
693 | 702 | ||
694 | fail_gunlock3: | 703 | fail_gunlock3: |
695 | gfs2_glock_dq_uninit(ghs + 1); | 704 | gfs2_glock_dq_uninit(ghs + 1); |
@@ -729,36 +738,56 @@ fail: | |||
729 | static int gfs2_create(struct inode *dir, struct dentry *dentry, | 738 | static int gfs2_create(struct inode *dir, struct dentry *dentry, |
730 | umode_t mode, bool excl) | 739 | umode_t mode, bool excl) |
731 | { | 740 | { |
732 | return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl); | 741 | return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl, NULL); |
733 | } | 742 | } |
734 | 743 | ||
735 | /** | 744 | /** |
736 | * gfs2_lookup - Look up a filename in a directory and return its inode | 745 | * __gfs2_lookup - Look up a filename in a directory and return its inode |
737 | * @dir: The directory inode | 746 | * @dir: The directory inode |
738 | * @dentry: The dentry of the new inode | 747 | * @dentry: The dentry of the new inode |
739 | * @nd: passed from Linux VFS, ignored by us | 748 | * @file: File to be opened |
749 | * @opened: atomic_open flags | ||
740 | * | 750 | * |
741 | * Called by the VFS layer. Lock dir and call gfs2_lookupi() | ||
742 | * | 751 | * |
743 | * Returns: errno | 752 | * Returns: errno |
744 | */ | 753 | */ |
745 | 754 | ||
746 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, | 755 | static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry, |
747 | unsigned int flags) | 756 | struct file *file, int *opened) |
748 | { | 757 | { |
749 | struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0); | 758 | struct inode *inode; |
750 | if (inode && !IS_ERR(inode)) { | 759 | struct dentry *d; |
751 | struct gfs2_glock *gl = GFS2_I(inode)->i_gl; | 760 | struct gfs2_holder gh; |
752 | struct gfs2_holder gh; | 761 | struct gfs2_glock *gl; |
753 | int error; | 762 | int error; |
754 | error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | 763 | |
755 | if (error) { | 764 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); |
756 | iput(inode); | 765 | if (!inode) |
757 | return ERR_PTR(error); | 766 | return NULL; |
758 | } | 767 | if (IS_ERR(inode)) |
759 | gfs2_glock_dq_uninit(&gh); | 768 | return ERR_CAST(inode); |
769 | |||
770 | gl = GFS2_I(inode)->i_gl; | ||
771 | error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
772 | if (error) { | ||
773 | iput(inode); | ||
774 | return ERR_PTR(error); | ||
760 | } | 775 | } |
761 | return d_splice_alias(inode, dentry); | 776 | |
777 | d = d_splice_alias(inode, dentry); | ||
778 | if (file && S_ISREG(inode->i_mode)) | ||
779 | error = finish_open(file, dentry, gfs2_open_common, opened); | ||
780 | |||
781 | gfs2_glock_dq_uninit(&gh); | ||
782 | if (error) | ||
783 | return ERR_PTR(error); | ||
784 | return d; | ||
785 | } | ||
786 | |||
787 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, | ||
788 | unsigned flags) | ||
789 | { | ||
790 | return __gfs2_lookup(dir, dentry, NULL, NULL); | ||
762 | } | 791 | } |
763 | 792 | ||
764 | /** | 793 | /** |
@@ -1076,7 +1105,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry, | |||
1076 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1) | 1105 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1) |
1077 | return -ENAMETOOLONG; | 1106 | return -ENAMETOOLONG; |
1078 | 1107 | ||
1079 | return gfs2_create_inode(dir, dentry, S_IFLNK | S_IRWXUGO, 0, symname, size, 0); | 1108 | return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0, NULL); |
1080 | } | 1109 | } |
1081 | 1110 | ||
1082 | /** | 1111 | /** |
@@ -1092,7 +1121,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1092 | { | 1121 | { |
1093 | struct gfs2_sbd *sdp = GFS2_SB(dir); | 1122 | struct gfs2_sbd *sdp = GFS2_SB(dir); |
1094 | unsigned dsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); | 1123 | unsigned dsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); |
1095 | return gfs2_create_inode(dir, dentry, S_IFDIR | mode, 0, NULL, dsize, 0); | 1124 | return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0, NULL); |
1096 | } | 1125 | } |
1097 | 1126 | ||
1098 | /** | 1127 | /** |
@@ -1107,7 +1136,43 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1107 | static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | 1136 | static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, |
1108 | dev_t dev) | 1137 | dev_t dev) |
1109 | { | 1138 | { |
1110 | return gfs2_create_inode(dir, dentry, mode, dev, NULL, 0, 0); | 1139 | return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0, NULL); |
1140 | } | ||
1141 | |||
1142 | /** | ||
1143 | * gfs2_atomic_open - Atomically open a file | ||
1144 | * @dir: The directory | ||
1145 | * @dentry: The proposed new entry | ||
1146 | * @file: The proposed new struct file | ||
1147 | * @flags: open flags | ||
1148 | * @mode: File mode | ||
1149 | * @opened: Flag to say whether the file has been opened or not | ||
1150 | * | ||
1151 | * Returns: error code or 0 for success | ||
1152 | */ | ||
1153 | |||
1154 | static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry, | ||
1155 | struct file *file, unsigned flags, | ||
1156 | umode_t mode, int *opened) | ||
1157 | { | ||
1158 | struct dentry *d; | ||
1159 | bool excl = !!(flags & O_EXCL); | ||
1160 | |||
1161 | d = __gfs2_lookup(dir, dentry, file, opened); | ||
1162 | if (IS_ERR(d)) | ||
1163 | return PTR_ERR(d); | ||
1164 | if (d == NULL) | ||
1165 | d = dentry; | ||
1166 | if (d->d_inode) { | ||
1167 | if (!(*opened & FILE_OPENED)) | ||
1168 | return finish_no_open(file, d); | ||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | if (!(flags & O_CREAT)) | ||
1173 | return -ENOENT; | ||
1174 | |||
1175 | return gfs2_create_inode(dir, dentry, file, S_IFREG | mode, 0, NULL, 0, excl, opened); | ||
1111 | } | 1176 | } |
1112 | 1177 | ||
1113 | /* | 1178 | /* |
@@ -1787,6 +1852,7 @@ const struct inode_operations gfs2_dir_iops = { | |||
1787 | .removexattr = gfs2_removexattr, | 1852 | .removexattr = gfs2_removexattr, |
1788 | .fiemap = gfs2_fiemap, | 1853 | .fiemap = gfs2_fiemap, |
1789 | .get_acl = gfs2_get_acl, | 1854 | .get_acl = gfs2_get_acl, |
1855 | .atomic_open = gfs2_atomic_open, | ||
1790 | }; | 1856 | }; |
1791 | 1857 | ||
1792 | const struct inode_operations gfs2_symlink_iops = { | 1858 | const struct inode_operations gfs2_symlink_iops = { |
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index c53c7477f6da..ba4d9492d422 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -109,6 +109,7 @@ extern int gfs2_permission(struct inode *inode, int mask); | |||
109 | extern int gfs2_setattr_simple(struct inode *inode, struct iattr *attr); | 109 | extern int gfs2_setattr_simple(struct inode *inode, struct iattr *attr); |
110 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); | 110 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); |
111 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | 111 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); |
112 | extern int gfs2_open_common(struct inode *inode, struct file *file); | ||
112 | 113 | ||
113 | extern const struct inode_operations gfs2_file_iops; | 114 | extern const struct inode_operations gfs2_file_iops; |
114 | extern const struct inode_operations gfs2_dir_iops; | 115 | extern const struct inode_operations gfs2_dir_iops; |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index b404f4853034..610613fb65b5 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -211,15 +211,16 @@ static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
211 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp) | 211 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp) |
212 | { | 212 | { |
213 | struct gfs2_trans *tr, *s; | 213 | struct gfs2_trans *tr, *s; |
214 | int oldest_tr = 1; | ||
214 | int ret; | 215 | int ret; |
215 | 216 | ||
216 | spin_lock(&sdp->sd_ail_lock); | 217 | spin_lock(&sdp->sd_ail_lock); |
217 | list_for_each_entry_safe_reverse(tr, s, &sdp->sd_ail1_list, tr_list) { | 218 | list_for_each_entry_safe_reverse(tr, s, &sdp->sd_ail1_list, tr_list) { |
218 | gfs2_ail1_empty_one(sdp, tr); | 219 | gfs2_ail1_empty_one(sdp, tr); |
219 | if (list_empty(&tr->tr_ail1_list)) | 220 | if (list_empty(&tr->tr_ail1_list) && oldest_tr) |
220 | list_move(&tr->tr_list, &sdp->sd_ail2_list); | 221 | list_move(&tr->tr_list, &sdp->sd_ail2_list); |
221 | else | 222 | else |
222 | break; | 223 | oldest_tr = 0; |
223 | } | 224 | } |
224 | ret = list_empty(&sdp->sd_ail1_list); | 225 | ret = list_empty(&sdp->sd_ail1_list); |
225 | spin_unlock(&sdp->sd_ail_lock); | 226 | spin_unlock(&sdp->sd_ail_lock); |
@@ -317,7 +318,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
317 | 318 | ||
318 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 319 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) |
319 | { | 320 | { |
320 | unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize); | 321 | unsigned reserved_blks = 7 * (4096 / sdp->sd_vfs->s_blocksize); |
321 | unsigned wanted = blks + reserved_blks; | 322 | unsigned wanted = blks + reserved_blks; |
322 | DEFINE_WAIT(wait); | 323 | DEFINE_WAIT(wait); |
323 | int did_wait = 0; | 324 | int did_wait = 0; |
@@ -545,6 +546,76 @@ void gfs2_ordered_del_inode(struct gfs2_inode *ip) | |||
545 | spin_unlock(&sdp->sd_ordered_lock); | 546 | spin_unlock(&sdp->sd_ordered_lock); |
546 | } | 547 | } |
547 | 548 | ||
549 | void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | ||
550 | { | ||
551 | struct buffer_head *bh = bd->bd_bh; | ||
552 | struct gfs2_glock *gl = bd->bd_gl; | ||
553 | |||
554 | gfs2_remove_from_ail(bd); | ||
555 | bd->bd_bh = NULL; | ||
556 | bh->b_private = NULL; | ||
557 | bd->bd_blkno = bh->b_blocknr; | ||
558 | bd->bd_ops = &gfs2_revoke_lops; | ||
559 | sdp->sd_log_num_revoke++; | ||
560 | atomic_inc(&gl->gl_revokes); | ||
561 | set_bit(GLF_LFLUSH, &gl->gl_flags); | ||
562 | list_add(&bd->bd_list, &sdp->sd_log_le_revoke); | ||
563 | } | ||
564 | |||
565 | void gfs2_write_revokes(struct gfs2_sbd *sdp) | ||
566 | { | ||
567 | struct gfs2_trans *tr; | ||
568 | struct gfs2_bufdata *bd, *tmp; | ||
569 | int have_revokes = 0; | ||
570 | int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64); | ||
571 | |||
572 | gfs2_ail1_empty(sdp); | ||
573 | spin_lock(&sdp->sd_ail_lock); | ||
574 | list_for_each_entry(tr, &sdp->sd_ail1_list, tr_list) { | ||
575 | list_for_each_entry(bd, &tr->tr_ail2_list, bd_ail_st_list) { | ||
576 | if (list_empty(&bd->bd_list)) { | ||
577 | have_revokes = 1; | ||
578 | goto done; | ||
579 | } | ||
580 | } | ||
581 | } | ||
582 | done: | ||
583 | spin_unlock(&sdp->sd_ail_lock); | ||
584 | if (have_revokes == 0) | ||
585 | return; | ||
586 | while (sdp->sd_log_num_revoke > max_revokes) | ||
587 | max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64); | ||
588 | max_revokes -= sdp->sd_log_num_revoke; | ||
589 | if (!sdp->sd_log_num_revoke) { | ||
590 | atomic_dec(&sdp->sd_log_blks_free); | ||
591 | /* If no blocks have been reserved, we need to also | ||
592 | * reserve a block for the header */ | ||
593 | if (!sdp->sd_log_blks_reserved) | ||
594 | atomic_dec(&sdp->sd_log_blks_free); | ||
595 | } | ||
596 | gfs2_log_lock(sdp); | ||
597 | spin_lock(&sdp->sd_ail_lock); | ||
598 | list_for_each_entry(tr, &sdp->sd_ail1_list, tr_list) { | ||
599 | list_for_each_entry_safe(bd, tmp, &tr->tr_ail2_list, bd_ail_st_list) { | ||
600 | if (max_revokes == 0) | ||
601 | goto out_of_blocks; | ||
602 | if (!list_empty(&bd->bd_list)) | ||
603 | continue; | ||
604 | gfs2_add_revoke(sdp, bd); | ||
605 | max_revokes--; | ||
606 | } | ||
607 | } | ||
608 | out_of_blocks: | ||
609 | spin_unlock(&sdp->sd_ail_lock); | ||
610 | gfs2_log_unlock(sdp); | ||
611 | |||
612 | if (!sdp->sd_log_num_revoke) { | ||
613 | atomic_inc(&sdp->sd_log_blks_free); | ||
614 | if (!sdp->sd_log_blks_reserved) | ||
615 | atomic_inc(&sdp->sd_log_blks_free); | ||
616 | } | ||
617 | } | ||
618 | |||
548 | /** | 619 | /** |
549 | * log_write_header - Get and initialize a journal header buffer | 620 | * log_write_header - Get and initialize a journal header buffer |
550 | * @sdp: The GFS2 superblock | 621 | * @sdp: The GFS2 superblock |
@@ -562,7 +633,6 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) | |||
562 | lh = page_address(page); | 633 | lh = page_address(page); |
563 | clear_page(lh); | 634 | clear_page(lh); |
564 | 635 | ||
565 | gfs2_ail1_empty(sdp); | ||
566 | tail = current_tail(sdp); | 636 | tail = current_tail(sdp); |
567 | 637 | ||
568 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 638 | lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); |
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 3566f35915e0..37216634f0aa 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h | |||
@@ -72,5 +72,7 @@ extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) | |||
72 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); | 72 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); |
73 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); | 73 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); |
74 | extern int gfs2_logd(void *data); | 74 | extern int gfs2_logd(void *data); |
75 | extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); | ||
76 | extern void gfs2_write_revokes(struct gfs2_sbd *sdp); | ||
75 | 77 | ||
76 | #endif /* __LOG_DOT_H__ */ | 78 | #endif /* __LOG_DOT_H__ */ |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 6c33d7b6e0c4..17c5b5d7dc88 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/gfs2_ondisk.h> | 16 | #include <linux/gfs2_ondisk.h> |
17 | #include <linux/bio.h> | 17 | #include <linux/bio.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/list_sort.h> | ||
19 | 20 | ||
20 | #include "gfs2.h" | 21 | #include "gfs2.h" |
21 | #include "incore.h" | 22 | #include "incore.h" |
@@ -401,6 +402,20 @@ static void gfs2_check_magic(struct buffer_head *bh) | |||
401 | kunmap_atomic(kaddr); | 402 | kunmap_atomic(kaddr); |
402 | } | 403 | } |
403 | 404 | ||
405 | static int blocknr_cmp(void *priv, struct list_head *a, struct list_head *b) | ||
406 | { | ||
407 | struct gfs2_bufdata *bda, *bdb; | ||
408 | |||
409 | bda = list_entry(a, struct gfs2_bufdata, bd_list); | ||
410 | bdb = list_entry(b, struct gfs2_bufdata, bd_list); | ||
411 | |||
412 | if (bda->bd_bh->b_blocknr < bdb->bd_bh->b_blocknr) | ||
413 | return -1; | ||
414 | if (bda->bd_bh->b_blocknr > bdb->bd_bh->b_blocknr) | ||
415 | return 1; | ||
416 | return 0; | ||
417 | } | ||
418 | |||
404 | static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, | 419 | static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, |
405 | unsigned int total, struct list_head *blist, | 420 | unsigned int total, struct list_head *blist, |
406 | bool is_databuf) | 421 | bool is_databuf) |
@@ -413,6 +428,7 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, | |||
413 | __be64 *ptr; | 428 | __be64 *ptr; |
414 | 429 | ||
415 | gfs2_log_lock(sdp); | 430 | gfs2_log_lock(sdp); |
431 | list_sort(NULL, blist, blocknr_cmp); | ||
416 | bd1 = bd2 = list_prepare_entry(bd1, blist, bd_list); | 432 | bd1 = bd2 = list_prepare_entry(bd1, blist, bd_list); |
417 | while(total) { | 433 | while(total) { |
418 | num = total; | 434 | num = total; |
@@ -590,6 +606,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
590 | struct page *page; | 606 | struct page *page; |
591 | unsigned int length; | 607 | unsigned int length; |
592 | 608 | ||
609 | gfs2_write_revokes(sdp); | ||
593 | if (!sdp->sd_log_num_revoke) | 610 | if (!sdp->sd_log_num_revoke) |
594 | return; | 611 | return; |
595 | 612 | ||
@@ -836,10 +853,6 @@ const struct gfs2_log_operations gfs2_revoke_lops = { | |||
836 | .lo_name = "revoke", | 853 | .lo_name = "revoke", |
837 | }; | 854 | }; |
838 | 855 | ||
839 | const struct gfs2_log_operations gfs2_rg_lops = { | ||
840 | .lo_name = "rg", | ||
841 | }; | ||
842 | |||
843 | const struct gfs2_log_operations gfs2_databuf_lops = { | 856 | const struct gfs2_log_operations gfs2_databuf_lops = { |
844 | .lo_before_commit = databuf_lo_before_commit, | 857 | .lo_before_commit = databuf_lo_before_commit, |
845 | .lo_after_commit = databuf_lo_after_commit, | 858 | .lo_after_commit = databuf_lo_after_commit, |
@@ -851,7 +864,6 @@ const struct gfs2_log_operations gfs2_databuf_lops = { | |||
851 | const struct gfs2_log_operations *gfs2_log_ops[] = { | 864 | const struct gfs2_log_operations *gfs2_log_ops[] = { |
852 | &gfs2_databuf_lops, | 865 | &gfs2_databuf_lops, |
853 | &gfs2_buf_lops, | 866 | &gfs2_buf_lops, |
854 | &gfs2_rg_lops, | ||
855 | &gfs2_revoke_lops, | 867 | &gfs2_revoke_lops, |
856 | NULL, | 868 | NULL, |
857 | }; | 869 | }; |
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index 87e062e05c92..9ca2e6438419 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h | |||
@@ -23,7 +23,6 @@ | |||
23 | extern const struct gfs2_log_operations gfs2_glock_lops; | 23 | extern const struct gfs2_log_operations gfs2_glock_lops; |
24 | extern const struct gfs2_log_operations gfs2_buf_lops; | 24 | extern const struct gfs2_log_operations gfs2_buf_lops; |
25 | extern const struct gfs2_log_operations gfs2_revoke_lops; | 25 | extern const struct gfs2_log_operations gfs2_revoke_lops; |
26 | extern const struct gfs2_log_operations gfs2_rg_lops; | ||
27 | extern const struct gfs2_log_operations gfs2_databuf_lops; | 26 | extern const struct gfs2_log_operations gfs2_databuf_lops; |
28 | 27 | ||
29 | extern const struct gfs2_log_operations *gfs2_log_ops[]; | 28 | extern const struct gfs2_log_operations *gfs2_log_ops[]; |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 1a89afb68472..0da390686c08 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -296,10 +296,6 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int | |||
296 | if (bd) { | 296 | if (bd) { |
297 | spin_lock(&sdp->sd_ail_lock); | 297 | spin_lock(&sdp->sd_ail_lock); |
298 | if (bd->bd_tr) { | 298 | if (bd->bd_tr) { |
299 | gfs2_remove_from_ail(bd); | ||
300 | bh->b_private = NULL; | ||
301 | bd->bd_bh = NULL; | ||
302 | bd->bd_blkno = bh->b_blocknr; | ||
303 | gfs2_trans_add_revoke(sdp, bd); | 299 | gfs2_trans_add_revoke(sdp, bd); |
304 | } | 300 | } |
305 | spin_unlock(&sdp->sd_ail_lock); | 301 | spin_unlock(&sdp->sd_ail_lock); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 60ede2a0f43f..0262c190b6f9 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -916,16 +916,16 @@ static int init_threads(struct gfs2_sbd *sdp, int undo) | |||
916 | goto fail_quotad; | 916 | goto fail_quotad; |
917 | 917 | ||
918 | p = kthread_run(gfs2_logd, sdp, "gfs2_logd"); | 918 | p = kthread_run(gfs2_logd, sdp, "gfs2_logd"); |
919 | error = IS_ERR(p); | 919 | if (IS_ERR(p)) { |
920 | if (error) { | 920 | error = PTR_ERR(p); |
921 | fs_err(sdp, "can't start logd thread: %d\n", error); | 921 | fs_err(sdp, "can't start logd thread: %d\n", error); |
922 | return error; | 922 | return error; |
923 | } | 923 | } |
924 | sdp->sd_logd_process = p; | 924 | sdp->sd_logd_process = p; |
925 | 925 | ||
926 | p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad"); | 926 | p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad"); |
927 | error = IS_ERR(p); | 927 | if (IS_ERR(p)) { |
928 | if (error) { | 928 | error = PTR_ERR(p); |
929 | fs_err(sdp, "can't start quotad thread: %d\n", error); | 929 | fs_err(sdp, "can't start quotad thread: %d\n", error); |
930 | goto fail; | 930 | goto fail; |
931 | } | 931 | } |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index c253b13722e8..3768c2f40e43 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -1154,11 +1154,6 @@ int gfs2_quota_sync(struct super_block *sb, int type) | |||
1154 | return error; | 1154 | return error; |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | static int gfs2_quota_sync_timeo(struct super_block *sb, int type) | ||
1158 | { | ||
1159 | return gfs2_quota_sync(sb, type); | ||
1160 | } | ||
1161 | |||
1162 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) | 1157 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) |
1163 | { | 1158 | { |
1164 | struct gfs2_quota_data *qd; | 1159 | struct gfs2_quota_data *qd; |
@@ -1414,7 +1409,7 @@ int gfs2_quotad(void *data) | |||
1414 | &tune->gt_statfs_quantum); | 1409 | &tune->gt_statfs_quantum); |
1415 | 1410 | ||
1416 | /* Update quota file */ | 1411 | /* Update quota file */ |
1417 | quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t, | 1412 | quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, |
1418 | "ad_timeo, &tune->gt_quota_quantum); | 1413 | "ad_timeo, &tune->gt_quota_quantum); |
1419 | 1414 | ||
1420 | /* Check for & recover partially truncated inodes */ | 1415 | /* Check for & recover partially truncated inodes */ |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 9809156e3d04..69317435faa7 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1288,13 +1288,15 @@ int gfs2_fitrim(struct file *filp, void __user *argp) | |||
1288 | minlen = max_t(u64, r.minlen, | 1288 | minlen = max_t(u64, r.minlen, |
1289 | q->limits.discard_granularity) >> bs_shift; | 1289 | q->limits.discard_granularity) >> bs_shift; |
1290 | 1290 | ||
1291 | if (end <= start || minlen > sdp->sd_max_rg_data) | ||
1292 | return -EINVAL; | ||
1293 | |||
1291 | rgd = gfs2_blk2rgrpd(sdp, start, 0); | 1294 | rgd = gfs2_blk2rgrpd(sdp, start, 0); |
1292 | rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); | 1295 | rgd_end = gfs2_blk2rgrpd(sdp, end, 0); |
1293 | 1296 | ||
1294 | if (end <= start || | 1297 | if ((gfs2_rgrpd_get_first(sdp) == gfs2_rgrpd_get_next(rgd_end)) |
1295 | minlen > sdp->sd_max_rg_data || | 1298 | && (start > rgd_end->rd_data0 + rgd_end->rd_data)) |
1296 | start > rgd_end->rd_data0 + rgd_end->rd_data) | 1299 | return -EINVAL; /* start is beyond the end of the fs */ |
1297 | return -EINVAL; | ||
1298 | 1300 | ||
1299 | while (1) { | 1301 | while (1) { |
1300 | 1302 | ||
@@ -1336,7 +1338,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) | |||
1336 | } | 1338 | } |
1337 | 1339 | ||
1338 | out: | 1340 | out: |
1339 | r.len = trimmed << 9; | 1341 | r.len = trimmed << bs_shift; |
1340 | if (copy_to_user(argp, &r, sizeof(r))) | 1342 | if (copy_to_user(argp, &r, sizeof(r))) |
1341 | return -EFAULT; | 1343 | return -EFAULT; |
1342 | 1344 | ||
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 7374907742a8..2b20d7046bf3 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -270,19 +270,12 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) | |||
270 | 270 | ||
271 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | 271 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
272 | { | 272 | { |
273 | struct gfs2_glock *gl = bd->bd_gl; | ||
274 | struct gfs2_trans *tr = current->journal_info; | 273 | struct gfs2_trans *tr = current->journal_info; |
275 | 274 | ||
276 | BUG_ON(!list_empty(&bd->bd_list)); | 275 | BUG_ON(!list_empty(&bd->bd_list)); |
277 | BUG_ON(!list_empty(&bd->bd_ail_st_list)); | 276 | gfs2_add_revoke(sdp, bd); |
278 | BUG_ON(!list_empty(&bd->bd_ail_gl_list)); | ||
279 | bd->bd_ops = &gfs2_revoke_lops; | ||
280 | tr->tr_touched = 1; | 277 | tr->tr_touched = 1; |
281 | tr->tr_num_revoke++; | 278 | tr->tr_num_revoke++; |
282 | sdp->sd_log_num_revoke++; | ||
283 | atomic_inc(&gl->gl_revokes); | ||
284 | set_bit(GLF_LFLUSH, &gl->gl_flags); | ||
285 | list_add(&bd->bd_list, &sdp->sd_log_le_revoke); | ||
286 | } | 279 | } |
287 | 280 | ||
288 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) | 281 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |