aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exofs/super.c')
-rw-r--r--fs/exofs/super.c211
1 files changed, 183 insertions, 28 deletions
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 047e92fa3af8..c57beddcc217 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -48,6 +48,7 @@
48 * struct to hold what we get from mount options 48 * struct to hold what we get from mount options
49 */ 49 */
50struct exofs_mountopt { 50struct exofs_mountopt {
51 bool is_osdname;
51 const char *dev_name; 52 const char *dev_name;
52 uint64_t pid; 53 uint64_t pid;
53 int timeout; 54 int timeout;
@@ -56,7 +57,7 @@ struct exofs_mountopt {
56/* 57/*
57 * exofs-specific mount-time options. 58 * exofs-specific mount-time options.
58 */ 59 */
59enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; 60enum { Opt_name, Opt_pid, Opt_to, Opt_err };
60 61
61/* 62/*
62 * Our mount-time options. These should ideally be 64-bit unsigned, but the 63 * Our mount-time options. These should ideally be 64-bit unsigned, but the
@@ -64,6 +65,7 @@ enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err };
64 * sufficient for most applications now. 65 * sufficient for most applications now.
65 */ 66 */
66static match_table_t tokens = { 67static match_table_t tokens = {
68 {Opt_name, "osdname=%s"},
67 {Opt_pid, "pid=%u"}, 69 {Opt_pid, "pid=%u"},
68 {Opt_to, "to=%u"}, 70 {Opt_to, "to=%u"},
69 {Opt_err, NULL} 71 {Opt_err, NULL}
@@ -94,6 +96,14 @@ static int parse_options(char *options, struct exofs_mountopt *opts)
94 96
95 token = match_token(p, tokens, args); 97 token = match_token(p, tokens, args);
96 switch (token) { 98 switch (token) {
99 case Opt_name:
100 opts->dev_name = match_strdup(&args[0]);
101 if (unlikely(!opts->dev_name)) {
102 EXOFS_ERR("Error allocating dev_name");
103 return -ENOMEM;
104 }
105 opts->is_osdname = true;
106 break;
97 case Opt_pid: 107 case Opt_pid:
98 if (0 == match_strlcpy(str, &args[0], sizeof(str))) 108 if (0 == match_strlcpy(str, &args[0], sizeof(str)))
99 return -EINVAL; 109 return -EINVAL;
@@ -150,12 +160,19 @@ static struct inode *exofs_alloc_inode(struct super_block *sb)
150 return &oi->vfs_inode; 160 return &oi->vfs_inode;
151} 161}
152 162
163static void exofs_i_callback(struct rcu_head *head)
164{
165 struct inode *inode = container_of(head, struct inode, i_rcu);
166 INIT_LIST_HEAD(&inode->i_dentry);
167 kmem_cache_free(exofs_inode_cachep, exofs_i(inode));
168}
169
153/* 170/*
154 * Remove an inode from the cache 171 * Remove an inode from the cache
155 */ 172 */
156static void exofs_destroy_inode(struct inode *inode) 173static void exofs_destroy_inode(struct inode *inode)
157{ 174{
158 kmem_cache_free(exofs_inode_cachep, exofs_i(inode)); 175 call_rcu(&inode->i_rcu, exofs_i_callback);
159} 176}
160 177
161/* 178/*
@@ -196,6 +213,101 @@ static void destroy_inodecache(void)
196static const struct super_operations exofs_sops; 213static const struct super_operations exofs_sops;
197static const struct export_operations exofs_export_ops; 214static const struct export_operations exofs_export_ops;
198 215
216static const struct osd_attr g_attr_sb_stats = ATTR_DEF(
217 EXOFS_APAGE_SB_DATA,
218 EXOFS_ATTR_SB_STATS,
219 sizeof(struct exofs_sb_stats));
220
221static int __sbi_read_stats(struct exofs_sb_info *sbi)
222{
223 struct osd_attr attrs[] = {
224 [0] = g_attr_sb_stats,
225 };
226 struct exofs_io_state *ios;
227 int ret;
228
229 ret = exofs_get_io_state(&sbi->layout, &ios);
230 if (unlikely(ret)) {
231 EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
232 return ret;
233 }
234
235 ios->cred = sbi->s_cred;
236
237 ios->in_attr = attrs;
238 ios->in_attr_len = ARRAY_SIZE(attrs);
239
240 ret = exofs_sbi_read(ios);
241 if (unlikely(ret)) {
242 EXOFS_ERR("Error reading super_block stats => %d\n", ret);
243 goto out;
244 }
245
246 ret = extract_attr_from_ios(ios, &attrs[0]);
247 if (ret) {
248 EXOFS_ERR("%s: extract_attr of sb_stats failed\n", __func__);
249 goto out;
250 }
251 if (attrs[0].len) {
252 struct exofs_sb_stats *ess;
253
254 if (unlikely(attrs[0].len != sizeof(*ess))) {
255 EXOFS_ERR("%s: Wrong version of exofs_sb_stats "
256 "size(%d) != expected(%zd)\n",
257 __func__, attrs[0].len, sizeof(*ess));
258 goto out;
259 }
260
261 ess = attrs[0].val_ptr;
262 sbi->s_nextid = le64_to_cpu(ess->s_nextid);
263 sbi->s_numfiles = le32_to_cpu(ess->s_numfiles);
264 }
265
266out:
267 exofs_put_io_state(ios);
268 return ret;
269}
270
271static void stats_done(struct exofs_io_state *ios, void *p)
272{
273 exofs_put_io_state(ios);
274 /* Good thanks nothing to do anymore */
275}
276
277/* Asynchronously write the stats attribute */
278int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
279{
280 struct osd_attr attrs[] = {
281 [0] = g_attr_sb_stats,
282 };
283 struct exofs_io_state *ios;
284 int ret;
285
286 ret = exofs_get_io_state(&sbi->layout, &ios);
287 if (unlikely(ret)) {
288 EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
289 return ret;
290 }
291
292 sbi->s_ess.s_nextid = cpu_to_le64(sbi->s_nextid);
293 sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles);
294 attrs[0].val_ptr = &sbi->s_ess;
295
296 ios->cred = sbi->s_cred;
297 ios->done = stats_done;
298 ios->private = sbi;
299 ios->out_attr = attrs;
300 ios->out_attr_len = ARRAY_SIZE(attrs);
301
302 ret = exofs_sbi_write(ios);
303 if (unlikely(ret)) {
304 EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
305 exofs_put_io_state(ios);
306 }
307
308 return ret;
309}
310
199/* 311/*
200 * Write the superblock to the OSD 312 * Write the superblock to the OSD
201 */ 313 */
@@ -206,18 +318,25 @@ int exofs_sync_fs(struct super_block *sb, int wait)
206 struct exofs_io_state *ios; 318 struct exofs_io_state *ios;
207 int ret = -ENOMEM; 319 int ret = -ENOMEM;
208 320
209 lock_super(sb); 321 fscb = kmalloc(sizeof(*fscb), GFP_KERNEL);
322 if (unlikely(!fscb))
323 return -ENOMEM;
324
210 sbi = sb->s_fs_info; 325 sbi = sb->s_fs_info;
211 fscb = &sbi->s_fscb;
212 326
327 /* NOTE: We no longer dirty the super_block anywhere in exofs. The
328 * reason we write the fscb here on unmount is so we can stay backwards
329 * compatible with fscb->s_version == 1. (What we are not compatible
330 * with is if a new version FS crashed and then we try to mount an old
331 * version). Otherwise the exofs_fscb is read-only from mkfs time. All
332 * the writeable info is set in exofs_sbi_write_stats() above.
333 */
213 ret = exofs_get_io_state(&sbi->layout, &ios); 334 ret = exofs_get_io_state(&sbi->layout, &ios);
214 if (ret) 335 if (unlikely(ret))
215 goto out; 336 goto out;
216 337
217 /* Note: We only write the changing part of the fscb. .i.e upto the 338 lock_super(sb);
218 * the fscb->s_dev_table_oid member. There is no read-modify-write 339
219 * here.
220 */
221 ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); 340 ios->length = offsetof(struct exofs_fscb, s_dev_table_oid);
222 memset(fscb, 0, ios->length); 341 memset(fscb, 0, ios->length);
223 fscb->s_nextid = cpu_to_le64(sbi->s_nextid); 342 fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
@@ -232,16 +351,17 @@ int exofs_sync_fs(struct super_block *sb, int wait)
232 ios->cred = sbi->s_cred; 351 ios->cred = sbi->s_cred;
233 352
234 ret = exofs_sbi_write(ios); 353 ret = exofs_sbi_write(ios);
235 if (unlikely(ret)) { 354 if (unlikely(ret))
236 EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); 355 EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
237 goto out; 356 else
238 } 357 sb->s_dirt = 0;
239 sb->s_dirt = 0; 358
240 359
360 unlock_super(sb);
241out: 361out:
242 EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); 362 EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret);
243 exofs_put_io_state(ios); 363 exofs_put_io_state(ios);
244 unlock_super(sb); 364 kfree(fscb);
245 return ret; 365 return ret;
246} 366}
247 367
@@ -285,13 +405,14 @@ static void exofs_put_super(struct super_block *sb)
285 int num_pend; 405 int num_pend;
286 struct exofs_sb_info *sbi = sb->s_fs_info; 406 struct exofs_sb_info *sbi = sb->s_fs_info;
287 407
288 if (sb->s_dirt)
289 exofs_write_super(sb);
290
291 /* make sure there are no pending commands */ 408 /* make sure there are no pending commands */
292 for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; 409 for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0;
293 num_pend = atomic_read(&sbi->s_curr_pending)) { 410 num_pend = atomic_read(&sbi->s_curr_pending)) {
294 wait_queue_head_t wq; 411 wait_queue_head_t wq;
412
413 printk(KERN_NOTICE "%s: !!Pending operations in flight. "
414 "This is a BUG. please report to osd-dev@open-osd.org\n",
415 __func__);
295 init_waitqueue_head(&wq); 416 init_waitqueue_head(&wq);
296 wait_event_timeout(wq, 417 wait_event_timeout(wq,
297 (atomic_read(&sbi->s_curr_pending) == 0), 418 (atomic_read(&sbi->s_curr_pending) == 0),
@@ -383,6 +504,23 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
383 return 0; 504 return 0;
384} 505}
385 506
507static unsigned __ra_pages(struct exofs_layout *layout)
508{
509 const unsigned _MIN_RA = 32; /* min 128K read-ahead */
510 unsigned ra_pages = layout->group_width * layout->stripe_unit /
511 PAGE_SIZE;
512 unsigned max_io_pages = exofs_max_io_pages(layout, ~0);
513
514 ra_pages *= 2; /* two stripes */
515 if (ra_pages < _MIN_RA)
516 ra_pages = roundup(_MIN_RA, ra_pages / 2);
517
518 if (ra_pages > max_io_pages)
519 ra_pages = max_io_pages;
520
521 return ra_pages;
522}
523
386/* @odi is valid only as long as @fscb_dev is valid */ 524/* @odi is valid only as long as @fscb_dev is valid */
387static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev, 525static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
388 struct osd_dev_info *odi) 526 struct osd_dev_info *odi)
@@ -488,7 +626,7 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
488 } 626 }
489 627
490 od = osduld_info_lookup(&odi); 628 od = osduld_info_lookup(&odi);
491 if (unlikely(IS_ERR(od))) { 629 if (IS_ERR(od)) {
492 ret = PTR_ERR(od); 630 ret = PTR_ERR(od);
493 EXOFS_ERR("ERROR: device requested is not found " 631 EXOFS_ERR("ERROR: device requested is not found "
494 "osd_name-%s =>%d\n", odi.osdname, ret); 632 "osd_name-%s =>%d\n", odi.osdname, ret);
@@ -551,9 +689,17 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
551 goto free_bdi; 689 goto free_bdi;
552 690
553 /* use mount options to fill superblock */ 691 /* use mount options to fill superblock */
554 od = osduld_path_lookup(opts->dev_name); 692 if (opts->is_osdname) {
693 struct osd_dev_info odi = {.systemid_len = 0};
694
695 odi.osdname_len = strlen(opts->dev_name);
696 odi.osdname = (u8 *)opts->dev_name;
697 od = osduld_info_lookup(&odi);
698 } else {
699 od = osduld_path_lookup(opts->dev_name);
700 }
555 if (IS_ERR(od)) { 701 if (IS_ERR(od)) {
556 ret = PTR_ERR(od); 702 ret = -EINVAL;
557 goto free_sbi; 703 goto free_sbi;
558 } 704 }
559 705
@@ -587,6 +733,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
587 goto free_sbi; 733 goto free_sbi;
588 734
589 sb->s_magic = le16_to_cpu(fscb.s_magic); 735 sb->s_magic = le16_to_cpu(fscb.s_magic);
736 /* NOTE: we read below to be backward compatible with old versions */
590 sbi->s_nextid = le64_to_cpu(fscb.s_nextid); 737 sbi->s_nextid = le64_to_cpu(fscb.s_nextid);
591 sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles); 738 sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles);
592 739
@@ -597,7 +744,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
597 ret = -EINVAL; 744 ret = -EINVAL;
598 goto free_sbi; 745 goto free_sbi;
599 } 746 }
600 if (le32_to_cpu(fscb.s_version) != EXOFS_FSCB_VER) { 747 if (le32_to_cpu(fscb.s_version) > EXOFS_FSCB_VER) {
601 EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n", 748 EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n",
602 EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version)); 749 EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version));
603 ret = -EINVAL; 750 ret = -EINVAL;
@@ -615,7 +762,10 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
615 goto free_sbi; 762 goto free_sbi;
616 } 763 }
617 764
765 __sbi_read_stats(sbi);
766
618 /* set up operation vectors */ 767 /* set up operation vectors */
768 sbi->bdi.ra_pages = __ra_pages(&sbi->layout);
619 sb->s_bdi = &sbi->bdi; 769 sb->s_bdi = &sbi->bdi;
620 sb->s_fs_info = sbi; 770 sb->s_fs_info = sbi;
621 sb->s_op = &exofs_sops; 771 sb->s_op = &exofs_sops;
@@ -645,6 +795,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
645 795
646 _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], 796 _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
647 sbi->layout.s_pid); 797 sbi->layout.s_pid);
798 if (opts->is_osdname)
799 kfree(opts->dev_name);
648 return 0; 800 return 0;
649 801
650free_sbi: 802free_sbi:
@@ -653,25 +805,28 @@ free_bdi:
653 EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", 805 EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n",
654 opts->dev_name, sbi->layout.s_pid, ret); 806 opts->dev_name, sbi->layout.s_pid, ret);
655 exofs_free_sbi(sbi); 807 exofs_free_sbi(sbi);
808 if (opts->is_osdname)
809 kfree(opts->dev_name);
656 return ret; 810 return ret;
657} 811}
658 812
659/* 813/*
660 * Set up the superblock (calls exofs_fill_super eventually) 814 * Set up the superblock (calls exofs_fill_super eventually)
661 */ 815 */
662static int exofs_get_sb(struct file_system_type *type, 816static struct dentry *exofs_mount(struct file_system_type *type,
663 int flags, const char *dev_name, 817 int flags, const char *dev_name,
664 void *data, struct vfsmount *mnt) 818 void *data)
665{ 819{
666 struct exofs_mountopt opts; 820 struct exofs_mountopt opts;
667 int ret; 821 int ret;
668 822
669 ret = parse_options(data, &opts); 823 ret = parse_options(data, &opts);
670 if (ret) 824 if (ret)
671 return ret; 825 return ERR_PTR(ret);
672 826
673 opts.dev_name = dev_name; 827 if (!opts.dev_name)
674 return get_sb_nodev(type, flags, &opts, exofs_fill_super, mnt); 828 opts.dev_name = dev_name;
829 return mount_nodev(type, flags, &opts, exofs_fill_super);
675} 830}
676 831
677/* 832/*
@@ -758,7 +913,7 @@ struct dentry *exofs_get_parent(struct dentry *child)
758 unsigned long ino = exofs_parent_ino(child); 913 unsigned long ino = exofs_parent_ino(child);
759 914
760 if (!ino) 915 if (!ino)
761 return NULL; 916 return ERR_PTR(-ESTALE);
762 917
763 return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); 918 return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino));
764} 919}
@@ -809,7 +964,7 @@ static const struct export_operations exofs_export_ops = {
809static struct file_system_type exofs_type = { 964static struct file_system_type exofs_type = {
810 .owner = THIS_MODULE, 965 .owner = THIS_MODULE,
811 .name = "exofs", 966 .name = "exofs",
812 .get_sb = exofs_get_sb, 967 .mount = exofs_mount,
813 .kill_sb = generic_shutdown_super, 968 .kill_sb = generic_shutdown_super,
814}; 969};
815 970