diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-13 13:29:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-13 13:29:21 -0500 |
commit | 1a52bb0b686844021597d190e562ab55d1210104 (patch) | |
tree | 7edf13509869a6a7f1f488a679f15ff6c3057c54 /fs/ceph | |
parent | 8638094e956a47dbb9a25166705a91e9a0981d52 (diff) | |
parent | 83eb26af0db71f2dfe551405c55d982288fa6178 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
ceph: ensure prealloc_blob is in place when removing xattr
rbd: initialize snap_rwsem in rbd_add()
ceph: enable/disable dentry complete flags via mount option
vfs: export symbol d_find_any_alias()
ceph: always initialize the dentry in open_root_dentry()
libceph: remove useless return value for osd_client __send_request()
ceph: avoid iput() while holding spinlock in ceph_dir_fsync
ceph: avoid useless dget/dput in encode_fh
ceph: dereference pointer after checking for NULL
crush: fix force for non-root TAKE
ceph: remove unnecessary d_fsdata conditional checks
ceph: Use kmemdup rather than duplicating its implementation
Fix up conflicts in fs/ceph/super.c (d_alloc_root() failure handling vs
always initialize the dentry in open_root_dentry)
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/dir.c | 76 | ||||
-rw-r--r-- | fs/ceph/export.c | 6 | ||||
-rw-r--r-- | fs/ceph/inode.c | 3 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 4 | ||||
-rw-r--r-- | fs/ceph/super.c | 16 | ||||
-rw-r--r-- | fs/ceph/super.h | 1 | ||||
-rw-r--r-- | fs/ceph/xattr.c | 22 |
7 files changed, 88 insertions, 40 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 74fd74719dc2..618246bc2196 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -973,7 +973,7 @@ static int dentry_lease_is_valid(struct dentry *dentry) | |||
973 | 973 | ||
974 | spin_lock(&dentry->d_lock); | 974 | spin_lock(&dentry->d_lock); |
975 | di = ceph_dentry(dentry); | 975 | di = ceph_dentry(dentry); |
976 | if (di && di->lease_session) { | 976 | if (di->lease_session) { |
977 | s = di->lease_session; | 977 | s = di->lease_session; |
978 | spin_lock(&s->s_cap_lock); | 978 | spin_lock(&s->s_cap_lock); |
979 | gen = s->s_cap_gen; | 979 | gen = s->s_cap_gen; |
@@ -1072,13 +1072,11 @@ static void ceph_d_release(struct dentry *dentry) | |||
1072 | struct ceph_dentry_info *di = ceph_dentry(dentry); | 1072 | struct ceph_dentry_info *di = ceph_dentry(dentry); |
1073 | 1073 | ||
1074 | dout("d_release %p\n", dentry); | 1074 | dout("d_release %p\n", dentry); |
1075 | if (di) { | 1075 | ceph_dentry_lru_del(dentry); |
1076 | ceph_dentry_lru_del(dentry); | 1076 | if (di->lease_session) |
1077 | if (di->lease_session) | 1077 | ceph_put_mds_session(di->lease_session); |
1078 | ceph_put_mds_session(di->lease_session); | 1078 | kmem_cache_free(ceph_dentry_cachep, di); |
1079 | kmem_cache_free(ceph_dentry_cachep, di); | 1079 | dentry->d_fsdata = NULL; |
1080 | dentry->d_fsdata = NULL; | ||
1081 | } | ||
1082 | } | 1080 | } |
1083 | 1081 | ||
1084 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, | 1082 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, |
@@ -1096,17 +1094,36 @@ static int ceph_snapdir_d_revalidate(struct dentry *dentry, | |||
1096 | */ | 1094 | */ |
1097 | void ceph_dir_set_complete(struct inode *inode) | 1095 | void ceph_dir_set_complete(struct inode *inode) |
1098 | { | 1096 | { |
1099 | /* not yet implemented */ | 1097 | struct dentry *dentry = d_find_any_alias(inode); |
1098 | |||
1099 | if (dentry && ceph_dentry(dentry) && | ||
1100 | ceph_test_mount_opt(ceph_sb_to_client(dentry->d_sb), DCACHE)) { | ||
1101 | dout(" marking %p (%p) complete\n", inode, dentry); | ||
1102 | set_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1103 | } | ||
1104 | dput(dentry); | ||
1100 | } | 1105 | } |
1101 | 1106 | ||
1102 | void ceph_dir_clear_complete(struct inode *inode) | 1107 | void ceph_dir_clear_complete(struct inode *inode) |
1103 | { | 1108 | { |
1104 | /* not yet implemented */ | 1109 | struct dentry *dentry = d_find_any_alias(inode); |
1110 | |||
1111 | if (dentry && ceph_dentry(dentry)) { | ||
1112 | dout(" marking %p (%p) complete\n", inode, dentry); | ||
1113 | set_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1114 | } | ||
1115 | dput(dentry); | ||
1105 | } | 1116 | } |
1106 | 1117 | ||
1107 | bool ceph_dir_test_complete(struct inode *inode) | 1118 | bool ceph_dir_test_complete(struct inode *inode) |
1108 | { | 1119 | { |
1109 | /* not yet implemented */ | 1120 | struct dentry *dentry = d_find_any_alias(inode); |
1121 | |||
1122 | if (dentry && ceph_dentry(dentry)) { | ||
1123 | dout(" marking %p (%p) NOT complete\n", inode, dentry); | ||
1124 | clear_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1125 | } | ||
1126 | dput(dentry); | ||
1110 | return false; | 1127 | return false; |
1111 | } | 1128 | } |
1112 | 1129 | ||
@@ -1220,6 +1237,7 @@ static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end, | |||
1220 | do { | 1237 | do { |
1221 | ceph_mdsc_get_request(req); | 1238 | ceph_mdsc_get_request(req); |
1222 | spin_unlock(&ci->i_unsafe_lock); | 1239 | spin_unlock(&ci->i_unsafe_lock); |
1240 | |||
1223 | dout("dir_fsync %p wait on tid %llu (until %llu)\n", | 1241 | dout("dir_fsync %p wait on tid %llu (until %llu)\n", |
1224 | inode, req->r_tid, last_tid); | 1242 | inode, req->r_tid, last_tid); |
1225 | if (req->r_timeout) { | 1243 | if (req->r_timeout) { |
@@ -1232,9 +1250,9 @@ static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end, | |||
1232 | } else { | 1250 | } else { |
1233 | wait_for_completion(&req->r_safe_completion); | 1251 | wait_for_completion(&req->r_safe_completion); |
1234 | } | 1252 | } |
1235 | spin_lock(&ci->i_unsafe_lock); | ||
1236 | ceph_mdsc_put_request(req); | 1253 | ceph_mdsc_put_request(req); |
1237 | 1254 | ||
1255 | spin_lock(&ci->i_unsafe_lock); | ||
1238 | if (ret || list_empty(head)) | 1256 | if (ret || list_empty(head)) |
1239 | break; | 1257 | break; |
1240 | req = list_entry(head->next, | 1258 | req = list_entry(head->next, |
@@ -1259,13 +1277,11 @@ void ceph_dentry_lru_add(struct dentry *dn) | |||
1259 | 1277 | ||
1260 | dout("dentry_lru_add %p %p '%.*s'\n", di, dn, | 1278 | dout("dentry_lru_add %p %p '%.*s'\n", di, dn, |
1261 | dn->d_name.len, dn->d_name.name); | 1279 | dn->d_name.len, dn->d_name.name); |
1262 | if (di) { | 1280 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
1263 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; | 1281 | spin_lock(&mdsc->dentry_lru_lock); |
1264 | spin_lock(&mdsc->dentry_lru_lock); | 1282 | list_add_tail(&di->lru, &mdsc->dentry_lru); |
1265 | list_add_tail(&di->lru, &mdsc->dentry_lru); | 1283 | mdsc->num_dentry++; |
1266 | mdsc->num_dentry++; | 1284 | spin_unlock(&mdsc->dentry_lru_lock); |
1267 | spin_unlock(&mdsc->dentry_lru_lock); | ||
1268 | } | ||
1269 | } | 1285 | } |
1270 | 1286 | ||
1271 | void ceph_dentry_lru_touch(struct dentry *dn) | 1287 | void ceph_dentry_lru_touch(struct dentry *dn) |
@@ -1275,12 +1291,10 @@ void ceph_dentry_lru_touch(struct dentry *dn) | |||
1275 | 1291 | ||
1276 | dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn, | 1292 | dout("dentry_lru_touch %p %p '%.*s' (offset %lld)\n", di, dn, |
1277 | dn->d_name.len, dn->d_name.name, di->offset); | 1293 | dn->d_name.len, dn->d_name.name, di->offset); |
1278 | if (di) { | 1294 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
1279 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; | 1295 | spin_lock(&mdsc->dentry_lru_lock); |
1280 | spin_lock(&mdsc->dentry_lru_lock); | 1296 | list_move_tail(&di->lru, &mdsc->dentry_lru); |
1281 | list_move_tail(&di->lru, &mdsc->dentry_lru); | 1297 | spin_unlock(&mdsc->dentry_lru_lock); |
1282 | spin_unlock(&mdsc->dentry_lru_lock); | ||
1283 | } | ||
1284 | } | 1298 | } |
1285 | 1299 | ||
1286 | void ceph_dentry_lru_del(struct dentry *dn) | 1300 | void ceph_dentry_lru_del(struct dentry *dn) |
@@ -1290,13 +1304,11 @@ void ceph_dentry_lru_del(struct dentry *dn) | |||
1290 | 1304 | ||
1291 | dout("dentry_lru_del %p %p '%.*s'\n", di, dn, | 1305 | dout("dentry_lru_del %p %p '%.*s'\n", di, dn, |
1292 | dn->d_name.len, dn->d_name.name); | 1306 | dn->d_name.len, dn->d_name.name); |
1293 | if (di) { | 1307 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; |
1294 | mdsc = ceph_sb_to_client(dn->d_sb)->mdsc; | 1308 | spin_lock(&mdsc->dentry_lru_lock); |
1295 | spin_lock(&mdsc->dentry_lru_lock); | 1309 | list_del_init(&di->lru); |
1296 | list_del_init(&di->lru); | 1310 | mdsc->num_dentry--; |
1297 | mdsc->num_dentry--; | 1311 | spin_unlock(&mdsc->dentry_lru_lock); |
1298 | spin_unlock(&mdsc->dentry_lru_lock); | ||
1299 | } | ||
1300 | } | 1312 | } |
1301 | 1313 | ||
1302 | /* | 1314 | /* |
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 9fbcdecaaccd..fbb2a643ef10 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c | |||
@@ -56,9 +56,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, | |||
56 | return -EINVAL; | 56 | return -EINVAL; |
57 | 57 | ||
58 | spin_lock(&dentry->d_lock); | 58 | spin_lock(&dentry->d_lock); |
59 | parent = dget(dentry->d_parent); | 59 | parent = dentry->d_parent; |
60 | spin_unlock(&dentry->d_lock); | ||
61 | |||
62 | if (*max_len >= connected_handle_length) { | 60 | if (*max_len >= connected_handle_length) { |
63 | dout("encode_fh %p connectable\n", dentry); | 61 | dout("encode_fh %p connectable\n", dentry); |
64 | cfh->ino = ceph_ino(dentry->d_inode); | 62 | cfh->ino = ceph_ino(dentry->d_inode); |
@@ -81,7 +79,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, | |||
81 | *max_len = handle_length; | 79 | *max_len = handle_length; |
82 | type = 255; | 80 | type = 255; |
83 | } | 81 | } |
84 | dput(parent); | 82 | spin_unlock(&dentry->d_lock); |
85 | return type; | 83 | return type; |
86 | } | 84 | } |
87 | 85 | ||
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 25283e7a37f8..2c489378b4cd 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -850,11 +850,12 @@ static void ceph_set_dentry_offset(struct dentry *dn) | |||
850 | { | 850 | { |
851 | struct dentry *dir = dn->d_parent; | 851 | struct dentry *dir = dn->d_parent; |
852 | struct inode *inode = dir->d_inode; | 852 | struct inode *inode = dir->d_inode; |
853 | struct ceph_inode_info *ci = ceph_inode(inode); | 853 | struct ceph_inode_info *ci; |
854 | struct ceph_dentry_info *di; | 854 | struct ceph_dentry_info *di; |
855 | 855 | ||
856 | BUG_ON(!inode); | 856 | BUG_ON(!inode); |
857 | 857 | ||
858 | ci = ceph_inode(inode); | ||
858 | di = ceph_dentry(dn); | 859 | di = ceph_dentry(dn); |
859 | 860 | ||
860 | spin_lock(&ci->i_ceph_lock); | 861 | spin_lock(&ci->i_ceph_lock); |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 6203d805eb45..23ab6a3f1825 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -2772,7 +2772,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, | |||
2772 | di = ceph_dentry(dentry); | 2772 | di = ceph_dentry(dentry); |
2773 | switch (h->action) { | 2773 | switch (h->action) { |
2774 | case CEPH_MDS_LEASE_REVOKE: | 2774 | case CEPH_MDS_LEASE_REVOKE: |
2775 | if (di && di->lease_session == session) { | 2775 | if (di->lease_session == session) { |
2776 | if (ceph_seq_cmp(di->lease_seq, seq) > 0) | 2776 | if (ceph_seq_cmp(di->lease_seq, seq) > 0) |
2777 | h->seq = cpu_to_le32(di->lease_seq); | 2777 | h->seq = cpu_to_le32(di->lease_seq); |
2778 | __ceph_mdsc_drop_dentry_lease(dentry); | 2778 | __ceph_mdsc_drop_dentry_lease(dentry); |
@@ -2781,7 +2781,7 @@ static void handle_lease(struct ceph_mds_client *mdsc, | |||
2781 | break; | 2781 | break; |
2782 | 2782 | ||
2783 | case CEPH_MDS_LEASE_RENEW: | 2783 | case CEPH_MDS_LEASE_RENEW: |
2784 | if (di && di->lease_session == session && | 2784 | if (di->lease_session == session && |
2785 | di->lease_gen == session->s_cap_gen && | 2785 | di->lease_gen == session->s_cap_gen && |
2786 | di->lease_renew_from && | 2786 | di->lease_renew_from && |
2787 | di->lease_renew_after == 0) { | 2787 | di->lease_renew_after == 0) { |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 48f61a12af66..00de2c9568cd 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -131,6 +131,8 @@ enum { | |||
131 | Opt_rbytes, | 131 | Opt_rbytes, |
132 | Opt_norbytes, | 132 | Opt_norbytes, |
133 | Opt_noasyncreaddir, | 133 | Opt_noasyncreaddir, |
134 | Opt_dcache, | ||
135 | Opt_nodcache, | ||
134 | Opt_ino32, | 136 | Opt_ino32, |
135 | }; | 137 | }; |
136 | 138 | ||
@@ -152,6 +154,8 @@ static match_table_t fsopt_tokens = { | |||
152 | {Opt_rbytes, "rbytes"}, | 154 | {Opt_rbytes, "rbytes"}, |
153 | {Opt_norbytes, "norbytes"}, | 155 | {Opt_norbytes, "norbytes"}, |
154 | {Opt_noasyncreaddir, "noasyncreaddir"}, | 156 | {Opt_noasyncreaddir, "noasyncreaddir"}, |
157 | {Opt_dcache, "dcache"}, | ||
158 | {Opt_nodcache, "nodcache"}, | ||
155 | {Opt_ino32, "ino32"}, | 159 | {Opt_ino32, "ino32"}, |
156 | {-1, NULL} | 160 | {-1, NULL} |
157 | }; | 161 | }; |
@@ -231,6 +235,12 @@ static int parse_fsopt_token(char *c, void *private) | |||
231 | case Opt_noasyncreaddir: | 235 | case Opt_noasyncreaddir: |
232 | fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; | 236 | fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; |
233 | break; | 237 | break; |
238 | case Opt_dcache: | ||
239 | fsopt->flags |= CEPH_MOUNT_OPT_DCACHE; | ||
240 | break; | ||
241 | case Opt_nodcache: | ||
242 | fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE; | ||
243 | break; | ||
234 | case Opt_ino32: | 244 | case Opt_ino32: |
235 | fsopt->flags |= CEPH_MOUNT_OPT_INO32; | 245 | fsopt->flags |= CEPH_MOUNT_OPT_INO32; |
236 | break; | 246 | break; |
@@ -377,6 +387,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) | |||
377 | seq_puts(m, ",norbytes"); | 387 | seq_puts(m, ",norbytes"); |
378 | if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR) | 388 | if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR) |
379 | seq_puts(m, ",noasyncreaddir"); | 389 | seq_puts(m, ",noasyncreaddir"); |
390 | if (fsopt->flags & CEPH_MOUNT_OPT_DCACHE) | ||
391 | seq_puts(m, ",dcache"); | ||
392 | else | ||
393 | seq_puts(m, ",nodcache"); | ||
380 | 394 | ||
381 | if (fsopt->wsize) | 395 | if (fsopt->wsize) |
382 | seq_printf(m, ",wsize=%d", fsopt->wsize); | 396 | seq_printf(m, ",wsize=%d", fsopt->wsize); |
@@ -647,10 +661,10 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc, | |||
647 | root = ERR_PTR(-ENOMEM); | 661 | root = ERR_PTR(-ENOMEM); |
648 | goto out; | 662 | goto out; |
649 | } | 663 | } |
650 | ceph_init_dentry(root); | ||
651 | } else { | 664 | } else { |
652 | root = d_obtain_alias(inode); | 665 | root = d_obtain_alias(inode); |
653 | } | 666 | } |
667 | ceph_init_dentry(root); | ||
654 | dout("open_root_inode success, root dentry is %p\n", root); | 668 | dout("open_root_inode success, root dentry is %p\n", root); |
655 | } else { | 669 | } else { |
656 | root = ERR_PTR(err); | 670 | root = ERR_PTR(err); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index cb3652b37271..1421f3d875a2 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ | 28 | #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ |
29 | #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ | 29 | #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ |
30 | #define CEPH_MOUNT_OPT_INO32 (1<<8) /* 32 bit inos */ | 30 | #define CEPH_MOUNT_OPT_INO32 (1<<8) /* 32 bit inos */ |
31 | #define CEPH_MOUNT_OPT_DCACHE (1<<9) /* use dcache for readdir etc */ | ||
31 | 32 | ||
32 | #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) | 33 | #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) |
33 | 34 | ||
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index a5e36e4488a7..857214ae8c08 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
@@ -818,6 +818,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) | |||
818 | struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); | 818 | struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); |
819 | int issued; | 819 | int issued; |
820 | int err; | 820 | int err; |
821 | int required_blob_size; | ||
821 | int dirty; | 822 | int dirty; |
822 | 823 | ||
823 | if (ceph_snap(inode) != CEPH_NOSNAP) | 824 | if (ceph_snap(inode) != CEPH_NOSNAP) |
@@ -833,14 +834,34 @@ int ceph_removexattr(struct dentry *dentry, const char *name) | |||
833 | return -EOPNOTSUPP; | 834 | return -EOPNOTSUPP; |
834 | } | 835 | } |
835 | 836 | ||
837 | err = -ENOMEM; | ||
836 | spin_lock(&ci->i_ceph_lock); | 838 | spin_lock(&ci->i_ceph_lock); |
837 | __build_xattrs(inode); | 839 | __build_xattrs(inode); |
840 | retry: | ||
838 | issued = __ceph_caps_issued(ci, NULL); | 841 | issued = __ceph_caps_issued(ci, NULL); |
839 | dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); | 842 | dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); |
840 | 843 | ||
841 | if (!(issued & CEPH_CAP_XATTR_EXCL)) | 844 | if (!(issued & CEPH_CAP_XATTR_EXCL)) |
842 | goto do_sync; | 845 | goto do_sync; |
843 | 846 | ||
847 | required_blob_size = __get_required_blob_size(ci, 0, 0); | ||
848 | |||
849 | if (!ci->i_xattrs.prealloc_blob || | ||
850 | required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { | ||
851 | struct ceph_buffer *blob; | ||
852 | |||
853 | spin_unlock(&ci->i_ceph_lock); | ||
854 | dout(" preaallocating new blob size=%d\n", required_blob_size); | ||
855 | blob = ceph_buffer_new(required_blob_size, GFP_NOFS); | ||
856 | if (!blob) | ||
857 | goto out; | ||
858 | spin_lock(&ci->i_ceph_lock); | ||
859 | if (ci->i_xattrs.prealloc_blob) | ||
860 | ceph_buffer_put(ci->i_xattrs.prealloc_blob); | ||
861 | ci->i_xattrs.prealloc_blob = blob; | ||
862 | goto retry; | ||
863 | } | ||
864 | |||
844 | err = __remove_xattr_by_name(ceph_inode(inode), name); | 865 | err = __remove_xattr_by_name(ceph_inode(inode), name); |
845 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 866 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
846 | ci->i_xattrs.dirty = true; | 867 | ci->i_xattrs.dirty = true; |
@@ -853,6 +874,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) | |||
853 | do_sync: | 874 | do_sync: |
854 | spin_unlock(&ci->i_ceph_lock); | 875 | spin_unlock(&ci->i_ceph_lock); |
855 | err = ceph_send_removexattr(dentry, name); | 876 | err = ceph_send_removexattr(dentry, name); |
877 | out: | ||
856 | return err; | 878 | return err; |
857 | } | 879 | } |
858 | 880 | ||