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 | |
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)
-rw-r--r-- | Documentation/filesystems/ceph.txt | 18 | ||||
-rw-r--r-- | drivers/block/rbd.c | 2 | ||||
-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 | ||||
-rw-r--r-- | fs/dcache.c | 11 | ||||
-rw-r--r-- | include/linux/dcache.h | 1 | ||||
-rw-r--r-- | net/ceph/crush/mapper.c | 11 | ||||
-rw-r--r-- | net/ceph/crypto.c | 3 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 21 |
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 | ||
129 | More Information | 137 | More 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 | ||
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 | ||
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 | ||
1478 | static 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 | */ | ||
1485 | struct 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 | 1494 | EXPORT_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 *); | |||
242 | extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *); | 242 | extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *); |
243 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); | 243 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); |
244 | extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); | 244 | extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); |
245 | extern struct dentry *d_find_any_alias(struct inode *inode); | ||
245 | extern struct dentry * d_obtain_alias(struct inode *); | 246 | extern struct dentry * d_obtain_alias(struct inode *); |
246 | extern void shrink_dcache_sb(struct super_block *); | 247 | extern void shrink_dcache_sb(struct super_block *); |
247 | extern void shrink_dcache_parent(struct dentry *); | 248 | extern 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); |
30 | static void __unregister_linger_request(struct ceph_osd_client *osdc, | 30 | static void __unregister_linger_request(struct ceph_osd_client *osdc, |
31 | struct ceph_osd_request *req); | 31 | struct ceph_osd_request *req); |
32 | static int __send_request(struct ceph_osd_client *osdc, | 32 | static void __send_request(struct ceph_osd_client *osdc, |
33 | struct ceph_osd_request *req); | 33 | struct ceph_osd_request *req); |
34 | 34 | ||
35 | static int op_needs_trail(int op) | 35 | static 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 | */ |
1025 | static int __send_request(struct ceph_osd_client *osdc, | 1025 | static 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 | ||
1742 | out_unlock: | 1733 | out_unlock: |