diff options
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 150 |
1 files changed, 108 insertions, 42 deletions
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 = { |