aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/xattr.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2015-05-01 05:49:16 -0400
committerIlya Dryomov <idryomov@gmail.com>2015-06-25 04:49:28 -0400
commit604d1b0245b97738cde4341944ad93edff4b2827 (patch)
tree05a75dfc1ddf4729405f9cb6ce2f405b8e47791e /fs/ceph/xattr.c
parent860560904962d08fd38666207c910065fe53e074 (diff)
ceph: take snap_rwsem when accessing snap realm's cached_context
When ceph inode's i_head_snapc is NULL, __ceph_mark_dirty_caps() accesses snap realm's cached_context. So we need take read lock of snap_rwsem. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/xattr.c')
-rw-r--r--fs/ceph/xattr.c45
1 files changed, 39 insertions, 6 deletions
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