aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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 /fs
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)
Diffstat (limited to 'fs')
-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
8 files changed, 97 insertions, 42 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
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