diff options
| -rw-r--r-- | Documentation/filesystems/ocfs2.txt | 7 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 29 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 3 | ||||
| -rw-r--r-- | fs/ocfs2/super.c | 15 |
4 files changed, 52 insertions, 2 deletions
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index 1f7ae144f6d8..5393e6611691 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt | |||
| @@ -87,3 +87,10 @@ dir_resv_level= (*) By default, directory reservations will scale with file | |||
| 87 | reservations - users should rarely need to change this | 87 | reservations - users should rarely need to change this |
| 88 | value. If allocation reservations are turned off, this | 88 | value. If allocation reservations are turned off, this |
| 89 | option will have no effect. | 89 | option will have no effect. |
| 90 | coherency=full (*) Disallow concurrent O_DIRECT writes, cluster inode | ||
| 91 | lock will be taken to force other nodes drop cache, | ||
| 92 | therefore full cluster coherency is guaranteed even | ||
| 93 | for O_DIRECT writes. | ||
| 94 | coherency=buffered Allow concurrent O_DIRECT writes without EX lock among | ||
| 95 | nodes, which gains high performance at risk of getting | ||
| 96 | stale data on other nodes. | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 13af9937bdda..9e8cc4346b76 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2225,6 +2225,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, | |||
| 2225 | struct file *file = iocb->ki_filp; | 2225 | struct file *file = iocb->ki_filp; |
| 2226 | struct inode *inode = file->f_path.dentry->d_inode; | 2226 | struct inode *inode = file->f_path.dentry->d_inode; |
| 2227 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2227 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 2228 | int full_coherency = !(osb->s_mount_opt & | ||
| 2229 | OCFS2_MOUNT_COHERENCY_BUFFERED); | ||
| 2228 | 2230 | ||
| 2229 | mlog_entry("(0x%p, %u, '%.*s')\n", file, | 2231 | mlog_entry("(0x%p, %u, '%.*s')\n", file, |
| 2230 | (unsigned int)nr_segs, | 2232 | (unsigned int)nr_segs, |
| @@ -2248,14 +2250,37 @@ relock: | |||
| 2248 | have_alloc_sem = 1; | 2250 | have_alloc_sem = 1; |
| 2249 | } | 2251 | } |
| 2250 | 2252 | ||
| 2251 | /* concurrent O_DIRECT writes are allowed */ | 2253 | /* |
| 2252 | rw_level = !direct_io; | 2254 | * Concurrent O_DIRECT writes are allowed with |
| 2255 | * mount_option "coherency=buffered". | ||
| 2256 | */ | ||
| 2257 | rw_level = (!direct_io || full_coherency); | ||
| 2258 | |||
| 2253 | ret = ocfs2_rw_lock(inode, rw_level); | 2259 | ret = ocfs2_rw_lock(inode, rw_level); |
| 2254 | if (ret < 0) { | 2260 | if (ret < 0) { |
| 2255 | mlog_errno(ret); | 2261 | mlog_errno(ret); |
| 2256 | goto out_sems; | 2262 | goto out_sems; |
| 2257 | } | 2263 | } |
| 2258 | 2264 | ||
| 2265 | /* | ||
| 2266 | * O_DIRECT writes with "coherency=full" need to take EX cluster | ||
| 2267 | * inode_lock to guarantee coherency. | ||
| 2268 | */ | ||
| 2269 | if (direct_io && full_coherency) { | ||
| 2270 | /* | ||
| 2271 | * We need to take and drop the inode lock to force | ||
| 2272 | * other nodes to drop their caches. Buffered I/O | ||
| 2273 | * already does this in write_begin(). | ||
| 2274 | */ | ||
| 2275 | ret = ocfs2_inode_lock(inode, NULL, 1); | ||
| 2276 | if (ret < 0) { | ||
| 2277 | mlog_errno(ret); | ||
| 2278 | goto out_sems; | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | ocfs2_inode_unlock(inode, 1); | ||
| 2282 | } | ||
| 2283 | |||
| 2259 | can_do_direct = direct_io; | 2284 | can_do_direct = direct_io; |
| 2260 | ret = ocfs2_prepare_inode_for_write(file, ppos, | 2285 | ret = ocfs2_prepare_inode_for_write(file, ppos, |
| 2261 | iocb->ki_left, appending, | 2286 | iocb->ki_left, appending, |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 687e291d73f2..3064feef1430 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -263,6 +263,9 @@ enum ocfs2_mount_options | |||
| 263 | control lists */ | 263 | control lists */ |
| 264 | OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */ | 264 | OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */ |
| 265 | OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */ | 265 | OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */ |
| 266 | |||
| 267 | OCFS2_MOUNT_COHERENCY_BUFFERED = 1 << 12 /* Allow concurrent O_DIRECT | ||
| 268 | writes */ | ||
| 266 | }; | 269 | }; |
| 267 | 270 | ||
| 268 | #define OCFS2_OSB_SOFT_RO 0x0001 | 271 | #define OCFS2_OSB_SOFT_RO 0x0001 |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index b578644b6637..9122d59f8127 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -177,6 +177,8 @@ enum { | |||
| 177 | Opt_noacl, | 177 | Opt_noacl, |
| 178 | Opt_usrquota, | 178 | Opt_usrquota, |
| 179 | Opt_grpquota, | 179 | Opt_grpquota, |
| 180 | Opt_coherency_buffered, | ||
| 181 | Opt_coherency_full, | ||
| 180 | Opt_resv_level, | 182 | Opt_resv_level, |
| 181 | Opt_dir_resv_level, | 183 | Opt_dir_resv_level, |
| 182 | Opt_err, | 184 | Opt_err, |
| @@ -205,6 +207,8 @@ static const match_table_t tokens = { | |||
| 205 | {Opt_noacl, "noacl"}, | 207 | {Opt_noacl, "noacl"}, |
| 206 | {Opt_usrquota, "usrquota"}, | 208 | {Opt_usrquota, "usrquota"}, |
| 207 | {Opt_grpquota, "grpquota"}, | 209 | {Opt_grpquota, "grpquota"}, |
| 210 | {Opt_coherency_buffered, "coherency=buffered"}, | ||
| 211 | {Opt_coherency_full, "coherency=full"}, | ||
| 208 | {Opt_resv_level, "resv_level=%u"}, | 212 | {Opt_resv_level, "resv_level=%u"}, |
| 209 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | 213 | {Opt_dir_resv_level, "dir_resv_level=%u"}, |
| 210 | {Opt_err, NULL} | 214 | {Opt_err, NULL} |
| @@ -1452,6 +1456,12 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
| 1452 | case Opt_grpquota: | 1456 | case Opt_grpquota: |
| 1453 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; | 1457 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; |
| 1454 | break; | 1458 | break; |
| 1459 | case Opt_coherency_buffered: | ||
| 1460 | mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
| 1461 | break; | ||
| 1462 | case Opt_coherency_full: | ||
| 1463 | mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
| 1464 | break; | ||
| 1455 | case Opt_acl: | 1465 | case Opt_acl: |
| 1456 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; | 1466 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; |
| 1457 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; | 1467 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; |
| @@ -1550,6 +1560,11 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
| 1550 | if (opts & OCFS2_MOUNT_GRPQUOTA) | 1560 | if (opts & OCFS2_MOUNT_GRPQUOTA) |
| 1551 | seq_printf(s, ",grpquota"); | 1561 | seq_printf(s, ",grpquota"); |
| 1552 | 1562 | ||
| 1563 | if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED) | ||
| 1564 | seq_printf(s, ",coherency=buffered"); | ||
| 1565 | else | ||
| 1566 | seq_printf(s, ",coherency=full"); | ||
| 1567 | |||
| 1553 | if (opts & OCFS2_MOUNT_NOUSERXATTR) | 1568 | if (opts & OCFS2_MOUNT_NOUSERXATTR) |
| 1554 | seq_printf(s, ",nouser_xattr"); | 1569 | seq_printf(s, ",nouser_xattr"); |
| 1555 | else | 1570 | else |
