diff options
Diffstat (limited to 'fs/gfs2/ops_file.c')
-rw-r--r-- | fs/gfs2/ops_file.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 3064f133bf3c..b3f1e0349ae0 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/ext2_fs.h> | 22 | #include <linux/ext2_fs.h> |
23 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
24 | #include <linux/lm_interface.h> | 24 | #include <linux/lm_interface.h> |
25 | #include <linux/writeback.h> | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | 27 | ||
27 | #include "gfs2.h" | 28 | #include "gfs2.h" |
@@ -71,7 +72,7 @@ static int gfs2_read_actor(read_descriptor_t *desc, struct page *page, | |||
71 | size = count; | 72 | size = count; |
72 | 73 | ||
73 | kaddr = kmap(page); | 74 | kaddr = kmap(page); |
74 | memcpy(desc->arg.buf, kaddr + offset, size); | 75 | memcpy(desc->arg.data, kaddr + offset, size); |
75 | kunmap(page); | 76 | kunmap(page); |
76 | 77 | ||
77 | desc->count = count - size; | 78 | desc->count = count - size; |
@@ -86,7 +87,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, | |||
86 | struct inode *inode = &ip->i_inode; | 87 | struct inode *inode = &ip->i_inode; |
87 | read_descriptor_t desc; | 88 | read_descriptor_t desc; |
88 | desc.written = 0; | 89 | desc.written = 0; |
89 | desc.arg.buf = buf; | 90 | desc.arg.data = buf; |
90 | desc.count = size; | 91 | desc.count = size; |
91 | desc.error = 0; | 92 | desc.error = 0; |
92 | do_generic_mapping_read(inode->i_mapping, ra_state, | 93 | do_generic_mapping_read(inode->i_mapping, ra_state, |
@@ -139,7 +140,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) | |||
139 | */ | 140 | */ |
140 | 141 | ||
141 | static int filldir_func(void *opaque, const char *name, unsigned int length, | 142 | static int filldir_func(void *opaque, const char *name, unsigned int length, |
142 | u64 offset, struct gfs2_inum *inum, | 143 | u64 offset, struct gfs2_inum_host *inum, |
143 | unsigned int type) | 144 | unsigned int type) |
144 | { | 145 | { |
145 | struct filldir_reg *fdr = (struct filldir_reg *)opaque; | 146 | struct filldir_reg *fdr = (struct filldir_reg *)opaque; |
@@ -253,7 +254,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) | |||
253 | u32 fsflags; | 254 | u32 fsflags; |
254 | 255 | ||
255 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); | 256 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); |
256 | error = gfs2_glock_nq_m_atime(1, &gh); | 257 | error = gfs2_glock_nq_atime(&gh); |
257 | if (error) | 258 | if (error) |
258 | return error; | 259 | return error; |
259 | 260 | ||
@@ -266,6 +267,24 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) | |||
266 | return error; | 267 | return error; |
267 | } | 268 | } |
268 | 269 | ||
270 | void gfs2_set_inode_flags(struct inode *inode) | ||
271 | { | ||
272 | struct gfs2_inode *ip = GFS2_I(inode); | ||
273 | struct gfs2_dinode_host *di = &ip->i_di; | ||
274 | unsigned int flags = inode->i_flags; | ||
275 | |||
276 | flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); | ||
277 | if (di->di_flags & GFS2_DIF_IMMUTABLE) | ||
278 | flags |= S_IMMUTABLE; | ||
279 | if (di->di_flags & GFS2_DIF_APPENDONLY) | ||
280 | flags |= S_APPEND; | ||
281 | if (di->di_flags & GFS2_DIF_NOATIME) | ||
282 | flags |= S_NOATIME; | ||
283 | if (di->di_flags & GFS2_DIF_SYNC) | ||
284 | flags |= S_SYNC; | ||
285 | inode->i_flags = flags; | ||
286 | } | ||
287 | |||
269 | /* Flags that can be set by user space */ | 288 | /* Flags that can be set by user space */ |
270 | #define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \ | 289 | #define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \ |
271 | GFS2_DIF_DIRECTIO| \ | 290 | GFS2_DIF_DIRECTIO| \ |
@@ -336,8 +355,9 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
336 | goto out_trans_end; | 355 | goto out_trans_end; |
337 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 356 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
338 | ip->i_di.di_flags = new_flags; | 357 | ip->i_di.di_flags = new_flags; |
339 | gfs2_dinode_out(&ip->i_di, bh->b_data); | 358 | gfs2_dinode_out(ip, bh->b_data); |
340 | brelse(bh); | 359 | brelse(bh); |
360 | gfs2_set_inode_flags(inode); | ||
341 | out_trans_end: | 361 | out_trans_end: |
342 | gfs2_trans_end(sdp); | 362 | gfs2_trans_end(sdp); |
343 | out: | 363 | out: |
@@ -425,7 +445,7 @@ static int gfs2_open(struct inode *inode, struct file *file) | |||
425 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); | 445 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); |
426 | file->private_data = fp; | 446 | file->private_data = fp; |
427 | 447 | ||
428 | if (S_ISREG(ip->i_di.di_mode)) { | 448 | if (S_ISREG(ip->i_inode.i_mode)) { |
429 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, | 449 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, |
430 | &i_gh); | 450 | &i_gh); |
431 | if (error) | 451 | if (error) |
@@ -484,16 +504,40 @@ static int gfs2_close(struct inode *inode, struct file *file) | |||
484 | * @file: the file that points to the dentry (we ignore this) | 504 | * @file: the file that points to the dentry (we ignore this) |
485 | * @dentry: the dentry that points to the inode to sync | 505 | * @dentry: the dentry that points to the inode to sync |
486 | * | 506 | * |
507 | * The VFS will flush "normal" data for us. We only need to worry | ||
508 | * about metadata here. For journaled data, we just do a log flush | ||
509 | * as we can't avoid it. Otherwise we can just bale out if datasync | ||
510 | * is set. For stuffed inodes we must flush the log in order to | ||
511 | * ensure that all data is on disk. | ||
512 | * | ||
513 | * The call to write_inode_now() is there to write back metadata and | ||
514 | * the inode itself. It does also try and write the data, but thats | ||
515 | * (hopefully) a no-op due to the VFS having already called filemap_fdatawrite() | ||
516 | * for us. | ||
517 | * | ||
487 | * Returns: errno | 518 | * Returns: errno |
488 | */ | 519 | */ |
489 | 520 | ||
490 | static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) | 521 | static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) |
491 | { | 522 | { |
492 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 523 | struct inode *inode = dentry->d_inode; |
524 | int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); | ||
525 | int ret = 0; | ||
493 | 526 | ||
494 | gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); | 527 | if (gfs2_is_jdata(GFS2_I(inode))) { |
528 | gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); | ||
529 | return 0; | ||
530 | } | ||
495 | 531 | ||
496 | return 0; | 532 | if (sync_state != 0) { |
533 | if (!datasync) | ||
534 | ret = write_inode_now(inode, 0); | ||
535 | |||
536 | if (gfs2_is_stuffed(GFS2_I(inode))) | ||
537 | gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); | ||
538 | } | ||
539 | |||
540 | return ret; | ||
497 | } | 541 | } |
498 | 542 | ||
499 | /** | 543 | /** |
@@ -515,7 +559,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) | |||
515 | 559 | ||
516 | if (!(fl->fl_flags & FL_POSIX)) | 560 | if (!(fl->fl_flags & FL_POSIX)) |
517 | return -ENOLCK; | 561 | return -ENOLCK; |
518 | if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) | 562 | if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) |
519 | return -ENOLCK; | 563 | return -ENOLCK; |
520 | 564 | ||
521 | if (sdp->sd_args.ar_localflocks) { | 565 | if (sdp->sd_args.ar_localflocks) { |
@@ -617,7 +661,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) | |||
617 | 661 | ||
618 | if (!(fl->fl_flags & FL_FLOCK)) | 662 | if (!(fl->fl_flags & FL_FLOCK)) |
619 | return -ENOLCK; | 663 | return -ENOLCK; |
620 | if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) | 664 | if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) |
621 | return -ENOLCK; | 665 | return -ENOLCK; |
622 | 666 | ||
623 | if (sdp->sd_args.ar_localflocks) | 667 | if (sdp->sd_args.ar_localflocks) |