diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-14 06:17:15 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2013-06-14 06:17:15 -0400 |
commit | 6d4ade986f9c8df31e68fd30643997f79cc5a5f8 (patch) | |
tree | f0758a7a9b008d0bd3665234a5074e3cf6f4d455 /fs/gfs2/file.c | |
parent | 5a00f3cc978be45b9d2597851bedaa40630bc597 (diff) |
GFS2: Add atomic_open support
I've restricted atomic_open to only operate on regular files, although
I still don't understand why atomic_open should not be possible also for
directories on GFS2. That can always be added in later though, if it
makes sense.
The ->atomic_open function can be passed negative dentries, which
in most cases means either ENOENT (->lookup) or a call to d_instantiate
(->create). In the GFS2 case though, we need to actually perform the
look up, since we do not know whether there has been a new inode created
on another node. The look up calls d_splice_alias which then tries to
rehash the dentry - so the solution here is to simply check for that
in d_splice_alias. The same issue is likely to affect any other cluster
filesystem implementing ->atomic_open
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: "J. Bruce Fields" <bfields fieldses org>
Cc: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r-- | fs/gfs2/file.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index ad0dc38d87ab..4ed6a03e565b 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -538,21 +538,30 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) | |||
538 | } | 538 | } |
539 | 539 | ||
540 | /** | 540 | /** |
541 | * gfs2_open - open a file | 541 | * gfs2_open_common - This is common to open and atomic_open |
542 | * @inode: the inode to open | 542 | * @inode: The inode being opened |
543 | * @file: the struct file for this opening | 543 | * @file: The file being opened |
544 | * | 544 | * |
545 | * Returns: errno | 545 | * This maybe called under a glock or not depending upon how it has |
546 | * been called. We must always be called under a glock for regular | ||
547 | * files, however. For other file types, it does not matter whether | ||
548 | * we hold the glock or not. | ||
549 | * | ||
550 | * Returns: Error code or 0 for success | ||
546 | */ | 551 | */ |
547 | 552 | ||
548 | static int gfs2_open(struct inode *inode, struct file *file) | 553 | int gfs2_open_common(struct inode *inode, struct file *file) |
549 | { | 554 | { |
550 | struct gfs2_inode *ip = GFS2_I(inode); | ||
551 | struct gfs2_holder i_gh; | ||
552 | struct gfs2_file *fp; | 555 | struct gfs2_file *fp; |
553 | int error; | 556 | int ret; |
554 | 557 | ||
555 | fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL); | 558 | if (S_ISREG(inode->i_mode)) { |
559 | ret = generic_file_open(inode, file); | ||
560 | if (ret) | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | fp = kzalloc(sizeof(struct gfs2_file), GFP_NOFS); | ||
556 | if (!fp) | 565 | if (!fp) |
557 | return -ENOMEM; | 566 | return -ENOMEM; |
558 | 567 | ||
@@ -560,29 +569,43 @@ static int gfs2_open(struct inode *inode, struct file *file) | |||
560 | 569 | ||
561 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); | 570 | gfs2_assert_warn(GFS2_SB(inode), !file->private_data); |
562 | file->private_data = fp; | 571 | file->private_data = fp; |
572 | return 0; | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * gfs2_open - open a file | ||
577 | * @inode: the inode to open | ||
578 | * @file: the struct file for this opening | ||
579 | * | ||
580 | * After atomic_open, this function is only used for opening files | ||
581 | * which are already cached. We must still get the glock for regular | ||
582 | * files to ensure that we have the file size uptodate for the large | ||
583 | * file check which is in the common code. That is only an issue for | ||
584 | * regular files though. | ||
585 | * | ||
586 | * Returns: errno | ||
587 | */ | ||
588 | |||
589 | static int gfs2_open(struct inode *inode, struct file *file) | ||
590 | { | ||
591 | struct gfs2_inode *ip = GFS2_I(inode); | ||
592 | struct gfs2_holder i_gh; | ||
593 | int error; | ||
594 | bool need_unlock = false; | ||
563 | 595 | ||
564 | if (S_ISREG(ip->i_inode.i_mode)) { | 596 | if (S_ISREG(ip->i_inode.i_mode)) { |
565 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, | 597 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, |
566 | &i_gh); | 598 | &i_gh); |
567 | if (error) | 599 | if (error) |
568 | goto fail; | 600 | return error; |
601 | need_unlock = true; | ||
602 | } | ||
569 | 603 | ||
570 | if (!(file->f_flags & O_LARGEFILE) && | 604 | error = gfs2_open_common(inode, file); |
571 | i_size_read(inode) > MAX_NON_LFS) { | ||
572 | error = -EOVERFLOW; | ||
573 | goto fail_gunlock; | ||
574 | } | ||
575 | 605 | ||
606 | if (need_unlock) | ||
576 | gfs2_glock_dq_uninit(&i_gh); | 607 | gfs2_glock_dq_uninit(&i_gh); |
577 | } | ||
578 | |||
579 | return 0; | ||
580 | 608 | ||
581 | fail_gunlock: | ||
582 | gfs2_glock_dq_uninit(&i_gh); | ||
583 | fail: | ||
584 | file->private_data = NULL; | ||
585 | kfree(fp); | ||
586 | return error; | 609 | return error; |
587 | } | 610 | } |
588 | 611 | ||