aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:29:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:29:21 -0500
commit1a52bb0b686844021597d190e562ab55d1210104 (patch)
tree7edf13509869a6a7f1f488a679f15ff6c3057c54
parent8638094e956a47dbb9a25166705a91e9a0981d52 (diff)
parent83eb26af0db71f2dfe551405c55d982288fa6178 (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)
-rw-r--r--Documentation/filesystems/ceph.txt18
-rw-r--r--drivers/block/rbd.c2
-rw-r--r--fs/ceph/dir.c76
-rw-r--r--fs/ceph/export.c6
-rw-r--r--fs/ceph/inode.c3
-rw-r--r--fs/ceph/mds_client.c4
-rw-r--r--fs/ceph/super.c16
-rw-r--r--fs/ceph/super.h1
-rw-r--r--fs/ceph/xattr.c22
-rw-r--r--fs/dcache.c11
-rw-r--r--include/linux/dcache.h1
-rw-r--r--net/ceph/crush/mapper.c11
-rw-r--r--net/ceph/crypto.c3
-rw-r--r--net/ceph/osd_client.c21
14 files changed, 128 insertions, 67 deletions
diff --git a/Documentation/filesystems/ceph.txt b/Documentation/filesystems/ceph.txt
index 763d8ebbbebd..d6030aa33376 100644
--- a/Documentation/filesystems/ceph.txt
+++ b/Documentation/filesystems/ceph.txt
@@ -119,12 +119,20 @@ Mount Options
119 must rely on TCP's error correction to detect data corruption 119 must rely on TCP's error correction to detect data corruption
120 in the data payload. 120 in the data payload.
121 121
122 noasyncreaddir 122 dcache
123 Disable client's use its local cache to satisfy readdir 123 Use the dcache contents to perform negative lookups and
124 requests. (This does not change correctness; the client uses 124 readdir when the client has the entire directory contents in
125 cached metadata only when a lease or capability ensures it is 125 its cache. (This does not change correctness; the client uses
126 valid.) 126 cached metadata only when a lease or capability ensures it is
127 valid.)
128
129 nodcache
130 Do not use the dcache as above. This avoids a significant amount of
131 complex code, sacrificing performance without affecting correctness,
132 and is useful for tracking down bugs.
127 133
134 noasyncreaddir
135 Do not use the dcache as above for readdir.
128 136
129More Information 137More Information
130================ 138================
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 148ab944378d..3fd31dec8c9c 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2184,6 +2184,8 @@ static ssize_t rbd_add(struct bus_type *bus,
2184 INIT_LIST_HEAD(&rbd_dev->node); 2184 INIT_LIST_HEAD(&rbd_dev->node);
2185 INIT_LIST_HEAD(&rbd_dev->snaps); 2185 INIT_LIST_HEAD(&rbd_dev->snaps);
2186 2186
2187 init_rwsem(&rbd_dev->header.snap_rwsem);
2188
2187 /* generate unique id: find highest unique id, add one */ 2189 /* generate unique id: find highest unique id, add one */
2188 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 2190 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
2189 2191
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
1084static int ceph_snapdir_d_revalidate(struct dentry *dentry, 1082static int ceph_snapdir_d_revalidate(struct dentry *dentry,
@@ -1096,17 +1094,36 @@ static int ceph_snapdir_d_revalidate(struct dentry *dentry,
1096 */ 1094 */
1097void ceph_dir_set_complete(struct inode *inode) 1095void 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
1102void ceph_dir_clear_complete(struct inode *inode) 1107void 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
1107bool ceph_dir_test_complete(struct inode *inode) 1118bool 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
1271void ceph_dentry_lru_touch(struct dentry *dn) 1287void 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
1286void ceph_dentry_lru_del(struct dentry *dn) 1300void 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);
840retry:
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)
853do_sync: 874do_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);
877out:
856 return err; 878 return err;
857} 879}
858 880
diff --git a/fs/dcache.c b/fs/dcache.c
index 616fedff011a..16a53cc2cc02 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1475,7 +1475,14 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
1475 return alias; 1475 return alias;
1476} 1476}
1477 1477
1478static struct dentry * d_find_any_alias(struct inode *inode) 1478/**
1479 * d_find_any_alias - find any alias for a given inode
1480 * @inode: inode to find an alias for
1481 *
1482 * If any aliases exist for the given inode, take and return a
1483 * reference for one of them. If no aliases exist, return %NULL.
1484 */
1485struct dentry *d_find_any_alias(struct inode *inode)
1479{ 1486{
1480 struct dentry *de; 1487 struct dentry *de;
1481 1488
@@ -1484,7 +1491,7 @@ static struct dentry * d_find_any_alias(struct inode *inode)
1484 spin_unlock(&inode->i_lock); 1491 spin_unlock(&inode->i_lock);
1485 return de; 1492 return de;
1486} 1493}
1487 1494EXPORT_SYMBOL(d_find_any_alias);
1488 1495
1489/** 1496/**
1490 * d_obtain_alias - find or allocate a dentry for a given inode 1497 * d_obtain_alias - find or allocate a dentry for a given inode
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 31f73220e7d7..d64a55b23afd 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -242,6 +242,7 @@ extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
242extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *); 242extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);
243extern struct dentry * d_splice_alias(struct inode *, struct dentry *); 243extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
244extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); 244extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
245extern struct dentry *d_find_any_alias(struct inode *inode);
245extern struct dentry * d_obtain_alias(struct inode *); 246extern struct dentry * d_obtain_alias(struct inode *);
246extern void shrink_dcache_sb(struct super_block *); 247extern void shrink_dcache_sb(struct super_block *);
247extern void shrink_dcache_parent(struct dentry *); 248extern void shrink_dcache_parent(struct dentry *);
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c
index 3a94eae7abe9..b79747c4b645 100644
--- a/net/ceph/crush/mapper.c
+++ b/net/ceph/crush/mapper.c
@@ -510,10 +510,15 @@ int crush_do_rule(struct crush_map *map,
510 switch (rule->steps[step].op) { 510 switch (rule->steps[step].op) {
511 case CRUSH_RULE_TAKE: 511 case CRUSH_RULE_TAKE:
512 w[0] = rule->steps[step].arg1; 512 w[0] = rule->steps[step].arg1;
513 if (force_pos >= 0) { 513
514 BUG_ON(force_context[force_pos] != w[0]); 514 /* find position in force_context/hierarchy */
515 while (force_pos >= 0 &&
516 force_context[force_pos] != w[0])
515 force_pos--; 517 force_pos--;
516 } 518 /* and move past it */
519 if (force_pos >= 0)
520 force_pos--;
521
517 wsize = 1; 522 wsize = 1;
518 break; 523 break;
519 524
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 85f3bc0a7062..b780cb7947dd 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -15,10 +15,9 @@ int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
15 const struct ceph_crypto_key *src) 15 const struct ceph_crypto_key *src)
16{ 16{
17 memcpy(dst, src, sizeof(struct ceph_crypto_key)); 17 memcpy(dst, src, sizeof(struct ceph_crypto_key));
18 dst->key = kmalloc(src->len, GFP_NOFS); 18 dst->key = kmemdup(src->key, src->len, GFP_NOFS);
19 if (!dst->key) 19 if (!dst->key)
20 return -ENOMEM; 20 return -ENOMEM;
21 memcpy(dst->key, src->key, src->len);
22 return 0; 21 return 0;
23} 22}
24 23
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index f4f3f58f5234..5e254055c910 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -29,8 +29,8 @@ static void __register_request(struct ceph_osd_client *osdc,
29 struct ceph_osd_request *req); 29 struct ceph_osd_request *req);
30static void __unregister_linger_request(struct ceph_osd_client *osdc, 30static void __unregister_linger_request(struct ceph_osd_client *osdc,
31 struct ceph_osd_request *req); 31 struct ceph_osd_request *req);
32static int __send_request(struct ceph_osd_client *osdc, 32static void __send_request(struct ceph_osd_client *osdc,
33 struct ceph_osd_request *req); 33 struct ceph_osd_request *req);
34 34
35static int op_needs_trail(int op) 35static int op_needs_trail(int op)
36{ 36{
@@ -1022,8 +1022,8 @@ out:
1022/* 1022/*
1023 * caller should hold map_sem (for read) and request_mutex 1023 * caller should hold map_sem (for read) and request_mutex
1024 */ 1024 */
1025static int __send_request(struct ceph_osd_client *osdc, 1025static void __send_request(struct ceph_osd_client *osdc,
1026 struct ceph_osd_request *req) 1026 struct ceph_osd_request *req)
1027{ 1027{
1028 struct ceph_osd_request_head *reqhead; 1028 struct ceph_osd_request_head *reqhead;
1029 1029
@@ -1041,7 +1041,6 @@ static int __send_request(struct ceph_osd_client *osdc,
1041 ceph_msg_get(req->r_request); /* send consumes a ref */ 1041 ceph_msg_get(req->r_request); /* send consumes a ref */
1042 ceph_con_send(&req->r_osd->o_con, req->r_request); 1042 ceph_con_send(&req->r_osd->o_con, req->r_request);
1043 req->r_sent = req->r_osd->o_incarnation; 1043 req->r_sent = req->r_osd->o_incarnation;
1044 return 0;
1045} 1044}
1046 1045
1047/* 1046/*
@@ -1726,17 +1725,9 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
1726 dout("send_request %p no up osds in pg\n", req); 1725 dout("send_request %p no up osds in pg\n", req);
1727 ceph_monc_request_next_osdmap(&osdc->client->monc); 1726 ceph_monc_request_next_osdmap(&osdc->client->monc);
1728 } else { 1727 } else {
1729 rc = __send_request(osdc, req); 1728 __send_request(osdc, req);
1730 if (rc) {
1731 if (nofail) {
1732 dout("osdc_start_request failed send, "
1733 " will retry %lld\n", req->r_tid);
1734 rc = 0;
1735 } else {
1736 __unregister_request(osdc, req);
1737 }
1738 }
1739 } 1729 }
1730 rc = 0;
1740 } 1731 }
1741 1732
1742out_unlock: 1733out_unlock: