aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/caps.c4
-rw-r--r--fs/ceph/inode.c15
-rw-r--r--fs/ceph/xattr.c45
3 files changed, 57 insertions, 7 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index f1dbcae7c75c..900c05fd77d8 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1413,9 +1413,11 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
1413 ceph_cap_string(was | mask)); 1413 ceph_cap_string(was | mask));
1414 ci->i_dirty_caps |= mask; 1414 ci->i_dirty_caps |= mask;
1415 if (was == 0) { 1415 if (was == 0) {
1416 if (!ci->i_head_snapc) 1416 if (!ci->i_head_snapc) {
1417 WARN_ON_ONCE(!rwsem_is_locked(&mdsc->snap_rwsem));
1417 ci->i_head_snapc = ceph_get_snap_context( 1418 ci->i_head_snapc = ceph_get_snap_context(
1418 ci->i_snap_realm->cached_context); 1419 ci->i_snap_realm->cached_context);
1420 }
1419 dout(" inode %p now dirty snapc %p auth cap %p\n", 1421 dout(" inode %p now dirty snapc %p auth cap %p\n",
1420 &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); 1422 &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap);
1421 BUG_ON(!list_empty(&ci->i_dirty_item)); 1423 BUG_ON(!list_empty(&ci->i_dirty_item));
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 1a68c0e38a52..1c991df276c9 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1727,6 +1727,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
1727 int mask = 0; 1727 int mask = 0;
1728 int err = 0; 1728 int err = 0;
1729 int inode_dirty_flags = 0; 1729 int inode_dirty_flags = 0;
1730 bool lock_snap_rwsem = false;
1730 1731
1731 if (ceph_snap(inode) != CEPH_NOSNAP) 1732 if (ceph_snap(inode) != CEPH_NOSNAP)
1732 return -EROFS; 1733 return -EROFS;
@@ -1742,6 +1743,18 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
1742 1743
1743 spin_lock(&ci->i_ceph_lock); 1744 spin_lock(&ci->i_ceph_lock);
1744 issued = __ceph_caps_issued(ci, NULL); 1745 issued = __ceph_caps_issued(ci, NULL);
1746
1747 if (!ci->i_head_snapc &&
1748 (issued & (CEPH_CAP_ANY_EXCL | CEPH_CAP_FILE_WR))) {
1749 lock_snap_rwsem = true;
1750 if (!down_read_trylock(&mdsc->snap_rwsem)) {
1751 spin_unlock(&ci->i_ceph_lock);
1752 down_read(&mdsc->snap_rwsem);
1753 spin_lock(&ci->i_ceph_lock);
1754 issued = __ceph_caps_issued(ci, NULL);
1755 }
1756 }
1757
1745 dout("setattr %p issued %s\n", inode, ceph_cap_string(issued)); 1758 dout("setattr %p issued %s\n", inode, ceph_cap_string(issued));
1746 1759
1747 if (ia_valid & ATTR_UID) { 1760 if (ia_valid & ATTR_UID) {
@@ -1890,6 +1903,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
1890 1903
1891 release &= issued; 1904 release &= issued;
1892 spin_unlock(&ci->i_ceph_lock); 1905 spin_unlock(&ci->i_ceph_lock);
1906 if (lock_snap_rwsem)
1907 up_read(&mdsc->snap_rwsem);
1893 1908
1894 if (inode_dirty_flags) 1909 if (inode_dirty_flags)
1895 __mark_inode_dirty(inode, inode_dirty_flags); 1910 __mark_inode_dirty(inode, inode_dirty_flags);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index cd7ffad4041d..c6f7d9b82085 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -911,6 +911,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
911 struct inode *inode = d_inode(dentry); 911 struct inode *inode = d_inode(dentry);
912 struct ceph_vxattr *vxattr; 912 struct ceph_vxattr *vxattr;
913 struct ceph_inode_info *ci = ceph_inode(inode); 913 struct ceph_inode_info *ci = ceph_inode(inode);
914 struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
914 int issued; 915 int issued;
915 int err; 916 int err;
916 int dirty = 0; 917 int dirty = 0;
@@ -920,6 +921,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
920 char *newval = NULL; 921 char *newval = NULL;
921 struct ceph_inode_xattr *xattr = NULL; 922 struct ceph_inode_xattr *xattr = NULL;
922 int required_blob_size; 923 int required_blob_size;
924 bool lock_snap_rwsem = false;
923 925
924 if (!ceph_is_valid_xattr(name)) 926 if (!ceph_is_valid_xattr(name))
925 return -EOPNOTSUPP; 927 return -EOPNOTSUPP;
@@ -951,9 +953,20 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
951 spin_lock(&ci->i_ceph_lock); 953 spin_lock(&ci->i_ceph_lock);
952retry: 954retry:
953 issued = __ceph_caps_issued(ci, NULL); 955 issued = __ceph_caps_issued(ci, NULL);
954 dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
955 if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) 956 if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL))
956 goto do_sync; 957 goto do_sync;
958
959 if (!lock_snap_rwsem && !ci->i_head_snapc) {
960 lock_snap_rwsem = true;
961 if (!down_read_trylock(&mdsc->snap_rwsem)) {
962 spin_unlock(&ci->i_ceph_lock);
963 down_read(&mdsc->snap_rwsem);
964 spin_lock(&ci->i_ceph_lock);
965 goto retry;
966 }
967 }
968
969 dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
957 __build_xattrs(inode); 970 __build_xattrs(inode);
958 971
959 required_blob_size = __get_required_blob_size(ci, name_len, val_len); 972 required_blob_size = __get_required_blob_size(ci, name_len, val_len);
@@ -966,7 +979,7 @@ retry:
966 dout(" preaallocating new blob size=%d\n", required_blob_size); 979 dout(" preaallocating new blob size=%d\n", required_blob_size);
967 blob = ceph_buffer_new(required_blob_size, GFP_NOFS); 980 blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
968 if (!blob) 981 if (!blob)
969 goto out; 982 goto do_sync_unlocked;
970 spin_lock(&ci->i_ceph_lock); 983 spin_lock(&ci->i_ceph_lock);
971 if (ci->i_xattrs.prealloc_blob) 984 if (ci->i_xattrs.prealloc_blob)
972 ceph_buffer_put(ci->i_xattrs.prealloc_blob); 985 ceph_buffer_put(ci->i_xattrs.prealloc_blob);
@@ -984,6 +997,8 @@ retry:
984 } 997 }
985 998
986 spin_unlock(&ci->i_ceph_lock); 999 spin_unlock(&ci->i_ceph_lock);
1000 if (lock_snap_rwsem)
1001 up_read(&mdsc->snap_rwsem);
987 if (dirty) 1002 if (dirty)
988 __mark_inode_dirty(inode, dirty); 1003 __mark_inode_dirty(inode, dirty);
989 return err; 1004 return err;
@@ -991,6 +1006,8 @@ retry:
991do_sync: 1006do_sync:
992 spin_unlock(&ci->i_ceph_lock); 1007 spin_unlock(&ci->i_ceph_lock);
993do_sync_unlocked: 1008do_sync_unlocked:
1009 if (lock_snap_rwsem)
1010 up_read(&mdsc->snap_rwsem);
994 err = ceph_sync_setxattr(dentry, name, value, size, flags); 1011 err = ceph_sync_setxattr(dentry, name, value, size, flags);
995out: 1012out:
996 kfree(newname); 1013 kfree(newname);
@@ -1044,10 +1061,12 @@ int __ceph_removexattr(struct dentry *dentry, const char *name)
1044 struct inode *inode = d_inode(dentry); 1061 struct inode *inode = d_inode(dentry);
1045 struct ceph_vxattr *vxattr; 1062 struct ceph_vxattr *vxattr;
1046 struct ceph_inode_info *ci = ceph_inode(inode); 1063 struct ceph_inode_info *ci = ceph_inode(inode);
1064 struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc;
1047 int issued; 1065 int issued;
1048 int err; 1066 int err;
1049 int required_blob_size; 1067 int required_blob_size;
1050 int dirty; 1068 int dirty;
1069 bool lock_snap_rwsem = false;
1051 1070
1052 if (!ceph_is_valid_xattr(name)) 1071 if (!ceph_is_valid_xattr(name))
1053 return -EOPNOTSUPP; 1072 return -EOPNOTSUPP;
@@ -1064,10 +1083,21 @@ int __ceph_removexattr(struct dentry *dentry, const char *name)
1064 spin_lock(&ci->i_ceph_lock); 1083 spin_lock(&ci->i_ceph_lock);
1065retry: 1084retry:
1066 issued = __ceph_caps_issued(ci, NULL); 1085 issued = __ceph_caps_issued(ci, NULL);
1067 dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued));
1068
1069 if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) 1086 if (ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL))
1070 goto do_sync; 1087 goto do_sync;
1088
1089 if (!lock_snap_rwsem && !ci->i_head_snapc) {
1090 lock_snap_rwsem = true;
1091 if (!down_read_trylock(&mdsc->snap_rwsem)) {
1092 spin_unlock(&ci->i_ceph_lock);
1093 down_read(&mdsc->snap_rwsem);
1094 spin_lock(&ci->i_ceph_lock);
1095 goto retry;
1096 }
1097 }
1098
1099 dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued));
1100
1071 __build_xattrs(inode); 1101 __build_xattrs(inode);
1072 1102
1073 required_blob_size = __get_required_blob_size(ci, 0, 0); 1103 required_blob_size = __get_required_blob_size(ci, 0, 0);
@@ -1080,7 +1110,7 @@ retry:
1080 dout(" preaallocating new blob size=%d\n", required_blob_size); 1110 dout(" preaallocating new blob size=%d\n", required_blob_size);
1081 blob = ceph_buffer_new(required_blob_size, GFP_NOFS); 1111 blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
1082 if (!blob) 1112 if (!blob)
1083 goto out; 1113 goto do_sync_unlocked;
1084 spin_lock(&ci->i_ceph_lock); 1114 spin_lock(&ci->i_ceph_lock);
1085 if (ci->i_xattrs.prealloc_blob) 1115 if (ci->i_xattrs.prealloc_blob)
1086 ceph_buffer_put(ci->i_xattrs.prealloc_blob); 1116 ceph_buffer_put(ci->i_xattrs.prealloc_blob);
@@ -1094,14 +1124,17 @@ retry:
1094 ci->i_xattrs.dirty = true; 1124 ci->i_xattrs.dirty = true;
1095 inode->i_ctime = CURRENT_TIME; 1125 inode->i_ctime = CURRENT_TIME;
1096 spin_unlock(&ci->i_ceph_lock); 1126 spin_unlock(&ci->i_ceph_lock);
1127 if (lock_snap_rwsem)
1128 up_read(&mdsc->snap_rwsem);
1097 if (dirty) 1129 if (dirty)
1098 __mark_inode_dirty(inode, dirty); 1130 __mark_inode_dirty(inode, dirty);
1099 return err; 1131 return err;
1100do_sync: 1132do_sync:
1101 spin_unlock(&ci->i_ceph_lock); 1133 spin_unlock(&ci->i_ceph_lock);
1102do_sync_unlocked: 1134do_sync_unlocked:
1135 if (lock_snap_rwsem)
1136 up_read(&mdsc->snap_rwsem);
1103 err = ceph_send_removexattr(dentry, name); 1137 err = ceph_send_removexattr(dentry, name);
1104out:
1105 return err; 1138 return err;
1106} 1139}
1107 1140