Blame view

fs/ceph/super.c 22.9 KB
16725b9d2   Sage Weil   ceph: super.c
1

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
2
  #include <linux/ceph/ceph_debug.h>
16725b9d2   Sage Weil   ceph: super.c
3
4
  
  #include <linux/backing-dev.h>
c309f0ab2   Sage Weil   ceph: clean up fs...
5
  #include <linux/ctype.h>
16725b9d2   Sage Weil   ceph: super.c
6
7
8
9
10
11
  #include <linux/fs.h>
  #include <linux/inet.h>
  #include <linux/in6.h>
  #include <linux/module.h>
  #include <linux/mount.h>
  #include <linux/parser.h>
16725b9d2   Sage Weil   ceph: super.c
12
13
  #include <linux/sched.h>
  #include <linux/seq_file.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
16725b9d2   Sage Weil   ceph: super.c
15
16
  #include <linux/statfs.h>
  #include <linux/string.h>
16725b9d2   Sage Weil   ceph: super.c
17

16725b9d2   Sage Weil   ceph: super.c
18
  #include "super.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
19
20
21
22
23
24
  #include "mds_client.h"
  
  #include <linux/ceph/decode.h>
  #include <linux/ceph/mon_client.h>
  #include <linux/ceph/auth.h>
  #include <linux/ceph/debugfs.h>
16725b9d2   Sage Weil   ceph: super.c
25
26
27
28
29
30
  
  /*
   * Ceph superblock operations
   *
   * Handle the basics of mounting, unmounting.
   */
16725b9d2   Sage Weil   ceph: super.c
31
32
33
34
35
  /*
   * super ops
   */
  static void ceph_put_super(struct super_block *s)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
36
  	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
16725b9d2   Sage Weil   ceph: super.c
37
38
39
  
  	dout("put_super
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
40
  	ceph_mdsc_close_sessions(fsc->mdsc);
5dfc589a8   Sage Weil   ceph: unregister ...
41
42
43
44
45
  
  	/*
  	 * ensure we release the bdi before put_anon_super releases
  	 * the device name.
  	 */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
46
47
  	if (s->s_bdi == &fsc->backing_dev_info) {
  		bdi_unregister(&fsc->backing_dev_info);
5dfc589a8   Sage Weil   ceph: unregister ...
48
49
  		s->s_bdi = NULL;
  	}
16725b9d2   Sage Weil   ceph: super.c
50
51
52
53
54
  	return;
  }
  
  static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
55
56
  	struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
  	struct ceph_monmap *monmap = fsc->client->monc.monmap;
16725b9d2   Sage Weil   ceph: super.c
57
58
59
60
61
62
  	struct ceph_statfs st;
  	u64 fsid;
  	int err;
  
  	dout("statfs
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
63
  	err = ceph_monc_do_statfs(&fsc->client->monc, &st);
16725b9d2   Sage Weil   ceph: super.c
64
65
66
67
68
69
70
71
72
73
74
75
  	if (err < 0)
  		return err;
  
  	/* fill in kstatfs */
  	buf->f_type = CEPH_SUPER_MAGIC;  /* ?? */
  
  	/*
  	 * express utilization in terms of large blocks to avoid
  	 * overflow on 32-bit machines.
  	 */
  	buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
  	buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
8f04d4227   Greg Farnum   ceph: report f_bf...
76
  	buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
16725b9d2   Sage Weil   ceph: super.c
77
78
79
80
  	buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
  
  	buf->f_files = le64_to_cpu(st.num_objects);
  	buf->f_ffree = -1;
558d3499b   Sage Weil   ceph: fix f_namel...
81
  	buf->f_namelen = NAME_MAX;
16725b9d2   Sage Weil   ceph: super.c
82
83
84
85
86
87
88
89
90
  	buf->f_frsize = PAGE_CACHE_SIZE;
  
  	/* leave fsid little-endian, regardless of host endianness */
  	fsid = *(u64 *)(&monmap->fsid) ^ *((u64 *)&monmap->fsid + 1);
  	buf->f_fsid.val[0] = fsid & 0xffffffff;
  	buf->f_fsid.val[1] = fsid >> 32;
  
  	return 0;
  }
2d9c98ae9   Sage Weil   ceph: make ->sync...
91
  static int ceph_sync_fs(struct super_block *sb, int wait)
16725b9d2   Sage Weil   ceph: super.c
92
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
93
  	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
2d9c98ae9   Sage Weil   ceph: make ->sync...
94
95
96
97
  
  	if (!wait) {
  		dout("sync_fs (non-blocking)
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
98
  		ceph_flush_dirty_caps(fsc->mdsc);
2d9c98ae9   Sage Weil   ceph: make ->sync...
99
100
101
102
103
104
105
  		dout("sync_fs (non-blocking) done
  ");
  		return 0;
  	}
  
  	dout("sync_fs (blocking)
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
106
107
  	ceph_osdc_sync(&fsc->client->osdc);
  	ceph_mdsc_sync(fsc->mdsc);
2d9c98ae9   Sage Weil   ceph: make ->sync...
108
109
  	dout("sync_fs (blocking) done
  ");
16725b9d2   Sage Weil   ceph: super.c
110
111
  	return 0;
  }
16725b9d2   Sage Weil   ceph: super.c
112
113
114
115
  /*
   * mount options
   */
  enum {
16725b9d2   Sage Weil   ceph: super.c
116
117
  	Opt_wsize,
  	Opt_rsize,
83817e35c   Sage Weil   ceph: rename rsiz...
118
  	Opt_rasize,
16725b9d2   Sage Weil   ceph: super.c
119
120
  	Opt_caps_wanted_delay_min,
  	Opt_caps_wanted_delay_max,
6e19a16ef   Sage Weil   ceph: clean up mo...
121
  	Opt_cap_release_safety,
16725b9d2   Sage Weil   ceph: super.c
122
  	Opt_readdir_max_entries,
23804d91f   Sage Weil   ceph: specify max...
123
  	Opt_readdir_max_bytes,
2baba2501   Yehuda Sadeh   ceph: writeback c...
124
  	Opt_congestion_kb,
e53c2fe07   Sage Weil   ceph: fix, clean ...
125
  	Opt_last_int,
16725b9d2   Sage Weil   ceph: super.c
126
127
  	/* int args above */
  	Opt_snapdirname,
e53c2fe07   Sage Weil   ceph: fix, clean ...
128
  	Opt_last_string,
16725b9d2   Sage Weil   ceph: super.c
129
  	/* string args above */
16725b9d2   Sage Weil   ceph: super.c
130
131
132
133
  	Opt_dirstat,
  	Opt_nodirstat,
  	Opt_rbytes,
  	Opt_norbytes,
16725b9d2   Sage Weil   ceph: super.c
134
  	Opt_noasyncreaddir,
a40dc6cc2   Sage Weil   ceph: enable/disa...
135
136
  	Opt_dcache,
  	Opt_nodcache,
ad1fee96c   Yehuda Sadeh   ceph: add ino32 m...
137
  	Opt_ino32,
16725b9d2   Sage Weil   ceph: super.c
138
  };
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
139
  static match_table_t fsopt_tokens = {
16725b9d2   Sage Weil   ceph: super.c
140
141
  	{Opt_wsize, "wsize=%d"},
  	{Opt_rsize, "rsize=%d"},
83817e35c   Sage Weil   ceph: rename rsiz...
142
  	{Opt_rasize, "rasize=%d"},
16725b9d2   Sage Weil   ceph: super.c
143
144
  	{Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
  	{Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
6e19a16ef   Sage Weil   ceph: clean up mo...
145
  	{Opt_cap_release_safety, "cap_release_safety=%d"},
16725b9d2   Sage Weil   ceph: super.c
146
  	{Opt_readdir_max_entries, "readdir_max_entries=%d"},
23804d91f   Sage Weil   ceph: specify max...
147
  	{Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
2baba2501   Yehuda Sadeh   ceph: writeback c...
148
  	{Opt_congestion_kb, "write_congestion_kb=%d"},
16725b9d2   Sage Weil   ceph: super.c
149
150
  	/* int args above */
  	{Opt_snapdirname, "snapdirname=%s"},
16725b9d2   Sage Weil   ceph: super.c
151
  	/* string args above */
16725b9d2   Sage Weil   ceph: super.c
152
153
154
155
  	{Opt_dirstat, "dirstat"},
  	{Opt_nodirstat, "nodirstat"},
  	{Opt_rbytes, "rbytes"},
  	{Opt_norbytes, "norbytes"},
16725b9d2   Sage Weil   ceph: super.c
156
  	{Opt_noasyncreaddir, "noasyncreaddir"},
a40dc6cc2   Sage Weil   ceph: enable/disa...
157
158
  	{Opt_dcache, "dcache"},
  	{Opt_nodcache, "nodcache"},
ad1fee96c   Yehuda Sadeh   ceph: add ino32 m...
159
  	{Opt_ino32, "ino32"},
16725b9d2   Sage Weil   ceph: super.c
160
161
  	{-1, NULL}
  };
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
162
  static int parse_fsopt_token(char *c, void *private)
c309f0ab2   Sage Weil   ceph: clean up fs...
163
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  	struct ceph_mount_options *fsopt = private;
  	substring_t argstr[MAX_OPT_ARGS];
  	int token, intval, ret;
  
  	token = match_token((char *)c, fsopt_tokens, argstr);
  	if (token < 0)
  		return -EINVAL;
  
  	if (token < Opt_last_int) {
  		ret = match_int(&argstr[0], &intval);
  		if (ret < 0) {
  			pr_err("bad mount option arg (not int) "
  			       "at '%s'
  ", c);
  			return ret;
c309f0ab2   Sage Weil   ceph: clean up fs...
179
  		}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
180
181
182
183
184
185
186
187
188
  		dout("got int token %d val %d
  ", token, intval);
  	} else if (token > Opt_last_int && token < Opt_last_string) {
  		dout("got string token %d val %s
  ", token,
  		     argstr[0].from);
  	} else {
  		dout("got token %d
  ", token);
c309f0ab2   Sage Weil   ceph: clean up fs...
189
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  	switch (token) {
  	case Opt_snapdirname:
  		kfree(fsopt->snapdir_name);
  		fsopt->snapdir_name = kstrndup(argstr[0].from,
  					       argstr[0].to-argstr[0].from,
  					       GFP_KERNEL);
  		if (!fsopt->snapdir_name)
  			return -ENOMEM;
  		break;
  
  		/* misc */
  	case Opt_wsize:
  		fsopt->wsize = intval;
  		break;
  	case Opt_rsize:
  		fsopt->rsize = intval;
  		break;
83817e35c   Sage Weil   ceph: rename rsiz...
207
208
209
  	case Opt_rasize:
  		fsopt->rasize = intval;
  		break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  	case Opt_caps_wanted_delay_min:
  		fsopt->caps_wanted_delay_min = intval;
  		break;
  	case Opt_caps_wanted_delay_max:
  		fsopt->caps_wanted_delay_max = intval;
  		break;
  	case Opt_readdir_max_entries:
  		fsopt->max_readdir = intval;
  		break;
  	case Opt_readdir_max_bytes:
  		fsopt->max_readdir_bytes = intval;
  		break;
  	case Opt_congestion_kb:
  		fsopt->congestion_kb = intval;
  		break;
  	case Opt_dirstat:
  		fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
  		break;
  	case Opt_nodirstat:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
  		break;
  	case Opt_rbytes:
  		fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
  		break;
  	case Opt_norbytes:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
  		break;
  	case Opt_noasyncreaddir:
  		fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
  		break;
a40dc6cc2   Sage Weil   ceph: enable/disa...
240
241
242
243
244
245
  	case Opt_dcache:
  		fsopt->flags |= CEPH_MOUNT_OPT_DCACHE;
  		break;
  	case Opt_nodcache:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE;
  		break;
ad1fee96c   Yehuda Sadeh   ceph: add ino32 m...
246
247
248
  	case Opt_ino32:
  		fsopt->flags |= CEPH_MOUNT_OPT_INO32;
  		break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
249
250
251
252
  	default:
  		BUG_ON(token);
  	}
  	return 0;
c309f0ab2   Sage Weil   ceph: clean up fs...
253
  }
16725b9d2   Sage Weil   ceph: super.c
254

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
255
  static void destroy_mount_options(struct ceph_mount_options *args)
16725b9d2   Sage Weil   ceph: super.c
256
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
257
258
259
260
261
  	dout("destroy_mount_options %p
  ", args);
  	kfree(args->snapdir_name);
  	kfree(args);
  }
16725b9d2   Sage Weil   ceph: super.c
262

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
263
264
265
266
267
268
269
270
271
272
  static int strcmp_null(const char *s1, const char *s2)
  {
  	if (!s1 && !s2)
  		return 0;
  	if (s1 && !s2)
  		return -1;
  	if (!s1 && s2)
  		return 1;
  	return strcmp(s1, s2);
  }
16725b9d2   Sage Weil   ceph: super.c
273

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
274
275
276
277
278
279
280
281
  static int compare_mount_options(struct ceph_mount_options *new_fsopt,
  				 struct ceph_options *new_opt,
  				 struct ceph_fs_client *fsc)
  {
  	struct ceph_mount_options *fsopt1 = new_fsopt;
  	struct ceph_mount_options *fsopt2 = fsc->mount_options;
  	int ofs = offsetof(struct ceph_mount_options, snapdir_name);
  	int ret;
16725b9d2   Sage Weil   ceph: super.c
282

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  	ret = memcmp(fsopt1, fsopt2, ofs);
  	if (ret)
  		return ret;
  
  	ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
  	if (ret)
  		return ret;
  
  	return ceph_compare_options(new_opt, fsc->client);
  }
  
  static int parse_mount_options(struct ceph_mount_options **pfsopt,
  			       struct ceph_options **popt,
  			       int flags, char *options,
  			       const char *dev_name,
  			       const char **path)
  {
  	struct ceph_mount_options *fsopt;
  	const char *dev_name_end;
  	int err = -ENOMEM;
  
  	fsopt = kzalloc(sizeof(*fsopt), GFP_KERNEL);
  	if (!fsopt)
  		return -ENOMEM;
  
  	dout("parse_mount_options %p, dev_name '%s'
  ", fsopt, dev_name);
80db8bea6   Noah Watkins   ceph: replace lea...
310
311
  	fsopt->sb_flags = flags;
  	fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
312

80db8bea6   Noah Watkins   ceph: replace lea...
313
314
315
  	fsopt->rsize = CEPH_RSIZE_DEFAULT;
  	fsopt->rasize = CEPH_RASIZE_DEFAULT;
  	fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
50aac4fec   Sage Weil   ceph: fix cap_wan...
316
317
  	fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
  	fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
80db8bea6   Noah Watkins   ceph: replace lea...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  	fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
  	fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT;
  	fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
  	fsopt->congestion_kb = default_congestion_kb();
  
  	/* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
  	err = -EINVAL;
  	if (!dev_name)
  		goto out;
  	*path = strstr(dev_name, ":/");
  	if (*path == NULL) {
  		pr_err("device name is missing path (no :/ in %s)
  ",
  				dev_name);
  		goto out;
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
334
335
336
  	dev_name_end = *path;
  	dout("device name '%.*s'
  ", (int)(dev_name_end - dev_name), dev_name);
16725b9d2   Sage Weil   ceph: super.c
337

16725b9d2   Sage Weil   ceph: super.c
338
339
340
341
  	/* path on server */
  	*path += 2;
  	dout("server path '%s'
  ", *path);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
342
343
344
345
346
347
348
349
  	err = ceph_parse_options(popt, options, dev_name, dev_name_end,
  				 parse_fsopt_token, (void *)fsopt);
  	if (err)
  		goto out;
  
  	/* success */
  	*pfsopt = fsopt;
  	return 0;
16725b9d2   Sage Weil   ceph: super.c
350

7b813c460   Sage Weil   ceph: reduce pars...
351
  out:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
352
353
  	destroy_mount_options(fsopt);
  	return err;
16725b9d2   Sage Weil   ceph: super.c
354
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
355
356
357
  /**
   * ceph_show_options - Show mount options in /proc/mounts
   * @m: seq_file to write to
34c80b1d9   Al Viro   vfs: switch ->sho...
358
   * @root: root of that (sub)tree
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
359
   */
34c80b1d9   Al Viro   vfs: switch ->sho...
360
  static int ceph_show_options(struct seq_file *m, struct dentry *root)
16725b9d2   Sage Weil   ceph: super.c
361
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
362
  	struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
363
364
365
366
367
368
369
370
371
372
373
374
  	struct ceph_mount_options *fsopt = fsc->mount_options;
  	struct ceph_options *opt = fsc->client->options;
  
  	if (opt->flags & CEPH_OPT_FSID)
  		seq_printf(m, ",fsid=%pU", &opt->fsid);
  	if (opt->flags & CEPH_OPT_NOSHARE)
  		seq_puts(m, ",noshare");
  	if (opt->flags & CEPH_OPT_NOCRC)
  		seq_puts(m, ",nocrc");
  
  	if (opt->name)
  		seq_printf(m, ",name=%s", opt->name);
8323c3aa7   Tommi Virtanen   ceph: Move secret...
375
  	if (opt->key)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  		seq_puts(m, ",secret=<hidden>");
  
  	if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
  		seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
  	if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
  		seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
  	if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
  		seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
  	if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
  		seq_printf(m, ",osdkeepalivetimeout=%d",
  			   opt->osd_keepalive_timeout);
  
  	if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
  		seq_puts(m, ",dirstat");
  	if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES) == 0)
  		seq_puts(m, ",norbytes");
  	if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
  		seq_puts(m, ",noasyncreaddir");
a40dc6cc2   Sage Weil   ceph: enable/disa...
394
395
396
397
  	if (fsopt->flags & CEPH_MOUNT_OPT_DCACHE)
  		seq_puts(m, ",dcache");
  	else
  		seq_puts(m, ",nodcache");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
398
399
400
  
  	if (fsopt->wsize)
  		seq_printf(m, ",wsize=%d", fsopt->wsize);
80456f867   Sage Weil   ceph: move readah...
401
  	if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
402
  		seq_printf(m, ",rsize=%d", fsopt->rsize);
83817e35c   Sage Weil   ceph: rename rsiz...
403
  	if (fsopt->rasize != CEPH_RASIZE_DEFAULT)
2151937d7   Sage Weil   ceph: fix rasize ...
404
  		seq_printf(m, ",rasize=%d", fsopt->rasize);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
  	if (fsopt->congestion_kb != default_congestion_kb())
  		seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
  	if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
  		seq_printf(m, ",caps_wanted_delay_min=%d",
  			 fsopt->caps_wanted_delay_min);
  	if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
  		seq_printf(m, ",caps_wanted_delay_max=%d",
  			   fsopt->caps_wanted_delay_max);
  	if (fsopt->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
  		seq_printf(m, ",cap_release_safety=%d",
  			   fsopt->cap_release_safety);
  	if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
  		seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
  	if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
  		seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
  	if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
  		seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
  	return 0;
16725b9d2   Sage Weil   ceph: super.c
423
424
425
  }
  
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
426
427
   * handle any mon messages the standard library doesn't understand.
   * return error if we don't either.
16725b9d2   Sage Weil   ceph: super.c
428
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
429
  static int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg)
16725b9d2   Sage Weil   ceph: super.c
430
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  	struct ceph_fs_client *fsc = client->private;
  	int type = le16_to_cpu(msg->hdr.type);
  
  	switch (type) {
  	case CEPH_MSG_MDS_MAP:
  		ceph_mdsc_handle_map(fsc->mdsc, msg);
  		return 0;
  
  	default:
  		return -1;
  	}
  }
  
  /*
   * create a new fs client
   */
0c6d4b4e2   H Hartley Sweeten   ceph/super.c: qui...
447
  static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
448
449
450
  					struct ceph_options *opt)
  {
  	struct ceph_fs_client *fsc;
6ab00d465   Sage Weil   libceph: create m...
451
452
453
454
  	const unsigned supported_features =
  		CEPH_FEATURE_FLOCK |
  		CEPH_FEATURE_DIRLAYOUTHASH;
  	const unsigned required_features = 0;
16725b9d2   Sage Weil   ceph: super.c
455
  	int err = -ENOMEM;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
456
457
  	fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
  	if (!fsc)
16725b9d2   Sage Weil   ceph: super.c
458
  		return ERR_PTR(-ENOMEM);
6ab00d465   Sage Weil   libceph: create m...
459
460
  	fsc->client = ceph_create_client(opt, fsc, supported_features,
  					 required_features);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
461
462
463
464
465
  	if (IS_ERR(fsc->client)) {
  		err = PTR_ERR(fsc->client);
  		goto fail;
  	}
  	fsc->client->extra_mon_dispatch = extra_mon_dispatch;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
466
  	fsc->client->monc.want_mdsmap = 1;
16725b9d2   Sage Weil   ceph: super.c
467

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
468
  	fsc->mount_options = fsopt;
16725b9d2   Sage Weil   ceph: super.c
469

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
470
471
  	fsc->sb = NULL;
  	fsc->mount_state = CEPH_MOUNT_MOUNTING;
16725b9d2   Sage Weil   ceph: super.c
472

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
473
  	atomic_long_set(&fsc->writeback_count, 0);
16725b9d2   Sage Weil   ceph: super.c
474

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
475
  	err = bdi_init(&fsc->backing_dev_info);
859e7b149   Sage Weil   ceph: init/destro...
476
  	if (err < 0)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
477
  		goto fail_client;
859e7b149   Sage Weil   ceph: init/destro...
478

16725b9d2   Sage Weil   ceph: super.c
479
  	err = -ENOMEM;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
480
481
482
483
484
  	/*
  	 * The number of concurrent works can be high but they don't need
  	 * to be processed in parallel, limit concurrency.
  	 */
  	fsc->wb_wq = alloc_workqueue("ceph-writeback", 0, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
485
  	if (fsc->wb_wq == NULL)
859e7b149   Sage Weil   ceph: init/destro...
486
  		goto fail_bdi;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
487
  	fsc->pg_inv_wq = alloc_workqueue("ceph-pg-invalid", 0, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
488
  	if (fsc->pg_inv_wq == NULL)
16725b9d2   Sage Weil   ceph: super.c
489
  		goto fail_wb_wq;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
490
  	fsc->trunc_wq = alloc_workqueue("ceph-trunc", 0, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
491
  	if (fsc->trunc_wq == NULL)
16725b9d2   Sage Weil   ceph: super.c
492
  		goto fail_pg_inv_wq;
b9bfb93ce   Sage Weil   ceph: move mempoo...
493
494
  	/* set up mempools */
  	err = -ENOMEM;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
495
496
497
  	fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
  			      fsc->mount_options->wsize >> PAGE_CACHE_SHIFT);
  	if (!fsc->wb_pagevec_pool)
b9bfb93ce   Sage Weil   ceph: move mempoo...
498
  		goto fail_trunc_wq;
85ccce43a   Sage Weil   ceph: clean up re...
499
  	/* caps */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
500
501
502
  	fsc->min_caps = fsopt->max_readdir;
  
  	return fsc;
b9bfb93ce   Sage Weil   ceph: move mempoo...
503

16725b9d2   Sage Weil   ceph: super.c
504
  fail_trunc_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
505
  	destroy_workqueue(fsc->trunc_wq);
16725b9d2   Sage Weil   ceph: super.c
506
  fail_pg_inv_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
507
  	destroy_workqueue(fsc->pg_inv_wq);
16725b9d2   Sage Weil   ceph: super.c
508
  fail_wb_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
509
  	destroy_workqueue(fsc->wb_wq);
859e7b149   Sage Weil   ceph: init/destro...
510
  fail_bdi:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
511
512
513
  	bdi_destroy(&fsc->backing_dev_info);
  fail_client:
  	ceph_destroy_client(fsc->client);
16725b9d2   Sage Weil   ceph: super.c
514
  fail:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
515
  	kfree(fsc);
16725b9d2   Sage Weil   ceph: super.c
516
517
  	return ERR_PTR(err);
  }
0c6d4b4e2   H Hartley Sweeten   ceph/super.c: qui...
518
  static void destroy_fs_client(struct ceph_fs_client *fsc)
16725b9d2   Sage Weil   ceph: super.c
519
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
520
521
  	dout("destroy_fs_client %p
  ", fsc);
16725b9d2   Sage Weil   ceph: super.c
522

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
523
524
525
  	destroy_workqueue(fsc->wb_wq);
  	destroy_workqueue(fsc->pg_inv_wq);
  	destroy_workqueue(fsc->trunc_wq);
16725b9d2   Sage Weil   ceph: super.c
526

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
527
  	bdi_destroy(&fsc->backing_dev_info);
a922d38fd   Sage Weil   ceph: close out m...
528

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
529
  	mempool_destroy(fsc->wb_pagevec_pool);
16725b9d2   Sage Weil   ceph: super.c
530

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
531
  	destroy_mount_options(fsc->mount_options);
5dfc589a8   Sage Weil   ceph: unregister ...
532

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
533
  	ceph_fs_debugfs_cleanup(fsc);
16725b9d2   Sage Weil   ceph: super.c
534

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
535
  	ceph_destroy_client(fsc->client);
16725b9d2   Sage Weil   ceph: super.c
536

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
537
538
539
  	kfree(fsc);
  	dout("destroy_fs_client %p done
  ", fsc);
16725b9d2   Sage Weil   ceph: super.c
540
541
542
  }
  
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
543
   * caches
0743304d8   Sage Weil   ceph: fix debugfs...
544
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
545
546
547
548
549
550
  struct kmem_cache *ceph_inode_cachep;
  struct kmem_cache *ceph_cap_cachep;
  struct kmem_cache *ceph_dentry_cachep;
  struct kmem_cache *ceph_file_cachep;
  
  static void ceph_inode_init_once(void *foo)
0743304d8   Sage Weil   ceph: fix debugfs...
551
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  	struct ceph_inode_info *ci = foo;
  	inode_init_once(&ci->vfs_inode);
  }
  
  static int __init init_caches(void)
  {
  	ceph_inode_cachep = kmem_cache_create("ceph_inode_info",
  				      sizeof(struct ceph_inode_info),
  				      __alignof__(struct ceph_inode_info),
  				      (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
  				      ceph_inode_init_once);
  	if (ceph_inode_cachep == NULL)
  		return -ENOMEM;
  
  	ceph_cap_cachep = KMEM_CACHE(ceph_cap,
  				     SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
  	if (ceph_cap_cachep == NULL)
  		goto bad_cap;
  
  	ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info,
  					SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
  	if (ceph_dentry_cachep == NULL)
  		goto bad_dentry;
  
  	ceph_file_cachep = KMEM_CACHE(ceph_file_info,
  				      SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
  	if (ceph_file_cachep == NULL)
  		goto bad_file;
0743304d8   Sage Weil   ceph: fix debugfs...
580
  	return 0;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
581
582
583
584
585
586
587
588
  
  bad_file:
  	kmem_cache_destroy(ceph_dentry_cachep);
  bad_dentry:
  	kmem_cache_destroy(ceph_cap_cachep);
  bad_cap:
  	kmem_cache_destroy(ceph_inode_cachep);
  	return -ENOMEM;
0743304d8   Sage Weil   ceph: fix debugfs...
589
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
590
591
592
593
594
595
596
  static void destroy_caches(void)
  {
  	kmem_cache_destroy(ceph_inode_cachep);
  	kmem_cache_destroy(ceph_cap_cachep);
  	kmem_cache_destroy(ceph_dentry_cachep);
  	kmem_cache_destroy(ceph_file_cachep);
  }
0743304d8   Sage Weil   ceph: fix debugfs...
597
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
598
599
   * ceph_umount_begin - initiate forced umount.  Tear down down the
   * mount, skipping steps that may hang while waiting for server(s).
16725b9d2   Sage Weil   ceph: super.c
600
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
601
  static void ceph_umount_begin(struct super_block *sb)
16725b9d2   Sage Weil   ceph: super.c
602
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
603
604
605
606
607
608
609
610
  	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
  
  	dout("ceph_umount_begin - starting forced umount
  ");
  	if (!fsc)
  		return;
  	fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
  	return;
16725b9d2   Sage Weil   ceph: super.c
611
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
612
613
614
615
616
617
618
619
620
621
  static const struct super_operations ceph_super_ops = {
  	.alloc_inode	= ceph_alloc_inode,
  	.destroy_inode	= ceph_destroy_inode,
  	.write_inode    = ceph_write_inode,
  	.sync_fs        = ceph_sync_fs,
  	.put_super	= ceph_put_super,
  	.show_options   = ceph_show_options,
  	.statfs		= ceph_statfs,
  	.umount_begin   = ceph_umount_begin,
  };
16725b9d2   Sage Weil   ceph: super.c
622
623
624
625
  /*
   * Bootstrap mount by opening the root directory.  Note the mount
   * @started time from caller, and time out if this takes too long.
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
626
  static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
16725b9d2   Sage Weil   ceph: super.c
627
628
629
  				       const char *path,
  				       unsigned long started)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
630
  	struct ceph_mds_client *mdsc = fsc->mdsc;
16725b9d2   Sage Weil   ceph: super.c
631
632
633
634
635
636
637
638
639
  	struct ceph_mds_request *req = NULL;
  	int err;
  	struct dentry *root;
  
  	/* open dir */
  	dout("open_root_inode opening '%s'
  ", path);
  	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
  	if (IS_ERR(req))
7e34bc524   Julia Lawall   fs/ceph: Use ERR_...
640
  		return ERR_CAST(req);
16725b9d2   Sage Weil   ceph: super.c
641
642
643
644
  	req->r_path1 = kstrdup(path, GFP_NOFS);
  	req->r_ino1.ino = CEPH_INO_ROOT;
  	req->r_ino1.snap = CEPH_NOSNAP;
  	req->r_started = started;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
645
  	req->r_timeout = fsc->client->options->mount_timeout * HZ;
16725b9d2   Sage Weil   ceph: super.c
646
647
648
649
  	req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
  	req->r_num_caps = 2;
  	err = ceph_mdsc_do_request(mdsc, NULL, req);
  	if (err == 0) {
3c5184ef1   Al Viro   ceph: d_alloc_roo...
650
651
  		struct inode *inode = req->r_target_inode;
  		req->r_target_inode = NULL;
16725b9d2   Sage Weil   ceph: super.c
652
653
  		dout("open_root_inode success
  ");
3c5184ef1   Al Viro   ceph: d_alloc_roo...
654
  		if (ceph_ino(inode) == CEPH_INO_ROOT &&
774ac21da   Sage Weil   ceph: initialize ...
655
  		    fsc->sb->s_root == NULL) {
3c5184ef1   Al Viro   ceph: d_alloc_roo...
656
657
658
659
660
661
  			root = d_alloc_root(inode);
  			if (!root) {
  				iput(inode);
  				root = ERR_PTR(-ENOMEM);
  				goto out;
  			}
774ac21da   Sage Weil   ceph: initialize ...
662
  		} else {
3c5184ef1   Al Viro   ceph: d_alloc_roo...
663
  			root = d_obtain_alias(inode);
774ac21da   Sage Weil   ceph: initialize ...
664
  		}
d46cfba53   Alex Elder   ceph: always init...
665
  		ceph_init_dentry(root);
16725b9d2   Sage Weil   ceph: super.c
666
667
668
669
670
  		dout("open_root_inode success, root dentry is %p
  ", root);
  	} else {
  		root = ERR_PTR(err);
  	}
3c5184ef1   Al Viro   ceph: d_alloc_roo...
671
  out:
16725b9d2   Sage Weil   ceph: super.c
672
673
674
  	ceph_mdsc_put_request(req);
  	return root;
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
675

16725b9d2   Sage Weil   ceph: super.c
676
677
678
  /*
   * mount: join the ceph cluster, and open root directory.
   */
a7f9fb205   Al Viro   convert ceph
679
  static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
16725b9d2   Sage Weil   ceph: super.c
680
681
  		      const char *path)
  {
16725b9d2   Sage Weil   ceph: super.c
682
  	int err;
16725b9d2   Sage Weil   ceph: super.c
683
684
  	unsigned long started = jiffies;  /* note the start time */
  	struct dentry *root;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
685
  	int first = 0;   /* first vfsmount for this super_block */
16725b9d2   Sage Weil   ceph: super.c
686
687
688
  
  	dout("mount start
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
689
  	mutex_lock(&fsc->client->mount_mutex);
16725b9d2   Sage Weil   ceph: super.c
690

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
691
  	err = __ceph_open_session(fsc->client, started);
16725b9d2   Sage Weil   ceph: super.c
692
693
  	if (err < 0)
  		goto out;
16725b9d2   Sage Weil   ceph: super.c
694
695
  	dout("mount opening root
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
696
  	root = open_root_dentry(fsc, "", started);
16725b9d2   Sage Weil   ceph: super.c
697
698
699
700
  	if (IS_ERR(root)) {
  		err = PTR_ERR(root);
  		goto out;
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
701
  	if (fsc->sb->s_root) {
16725b9d2   Sage Weil   ceph: super.c
702
  		dput(root);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
703
704
705
706
707
708
709
710
  	} else {
  		fsc->sb->s_root = root;
  		first = 1;
  
  		err = ceph_fs_debugfs_init(fsc);
  		if (err < 0)
  			goto fail;
  	}
16725b9d2   Sage Weil   ceph: super.c
711
712
713
714
715
716
  
  	if (path[0] == 0) {
  		dget(root);
  	} else {
  		dout("mount opening base mountpoint
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
717
  		root = open_root_dentry(fsc, path, started);
16725b9d2   Sage Weil   ceph: super.c
718
719
  		if (IS_ERR(root)) {
  			err = PTR_ERR(root);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
720
  			goto fail;
16725b9d2   Sage Weil   ceph: super.c
721
722
  		}
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
723
  	fsc->mount_state = CEPH_MOUNT_MOUNTED;
16725b9d2   Sage Weil   ceph: super.c
724
725
  	dout("mount success
  ");
a7f9fb205   Al Viro   convert ceph
726
727
  	mutex_unlock(&fsc->client->mount_mutex);
  	return root;
16725b9d2   Sage Weil   ceph: super.c
728
729
  
  out:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
730
  	mutex_unlock(&fsc->client->mount_mutex);
a7f9fb205   Al Viro   convert ceph
731
  	return ERR_PTR(err);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
732
733
734
735
736
737
738
  
  fail:
  	if (first) {
  		dput(fsc->sb->s_root);
  		fsc->sb->s_root = NULL;
  	}
  	goto out;
16725b9d2   Sage Weil   ceph: super.c
739
740
741
742
  }
  
  static int ceph_set_super(struct super_block *s, void *data)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
743
  	struct ceph_fs_client *fsc = data;
16725b9d2   Sage Weil   ceph: super.c
744
745
746
747
  	int ret;
  
  	dout("set_super %p data %p
  ", s, data);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
748
  	s->s_flags = fsc->mount_options->sb_flags;
16725b9d2   Sage Weil   ceph: super.c
749
  	s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
750
751
  	s->s_fs_info = fsc;
  	fsc->sb = s;
16725b9d2   Sage Weil   ceph: super.c
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  
  	s->s_op = &ceph_super_ops;
  	s->s_export_op = &ceph_export_ops;
  
  	s->s_time_gran = 1000;  /* 1000 ns == 1 us */
  
  	ret = set_anon_super(s, NULL);  /* what is that second arg for? */
  	if (ret != 0)
  		goto fail;
  
  	return ret;
  
  fail:
  	s->s_fs_info = NULL;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
766
  	fsc->sb = NULL;
16725b9d2   Sage Weil   ceph: super.c
767
768
769
770
771
772
773
774
  	return ret;
  }
  
  /*
   * share superblock if same fs AND options
   */
  static int ceph_compare_super(struct super_block *sb, void *data)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
775
776
777
778
  	struct ceph_fs_client *new = data;
  	struct ceph_mount_options *fsopt = new->mount_options;
  	struct ceph_options *opt = new->client->options;
  	struct ceph_fs_client *other = ceph_sb_to_client(sb);
16725b9d2   Sage Weil   ceph: super.c
779
780
781
  
  	dout("ceph_compare_super %p
  ", sb);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
782
783
784
785
786
  
  	if (compare_mount_options(fsopt, opt, other)) {
  		dout("monitor(s)/mount options don't match
  ");
  		return 0;
16725b9d2   Sage Weil   ceph: super.c
787
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
788
789
790
791
792
793
794
  	if ((opt->flags & CEPH_OPT_FSID) &&
  	    ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
  		dout("fsid doesn't match
  ");
  		return 0;
  	}
  	if (fsopt->sb_flags != other->mount_options->sb_flags) {
16725b9d2   Sage Weil   ceph: super.c
795
796
797
798
799
800
801
802
803
804
  		dout("flags differ
  ");
  		return 0;
  	}
  	return 1;
  }
  
  /*
   * construct our own bdi so we can control readahead, etc.
   */
00d5643e7   Jeff Mahoney   ceph: fix atomic6...
805
  static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
31e0cf8f6   Sage Weil   ceph: name bdi ce...
806

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
807
808
  static int ceph_register_bdi(struct super_block *sb,
  			     struct ceph_fs_client *fsc)
16725b9d2   Sage Weil   ceph: super.c
809
810
  {
  	int err;
83817e35c   Sage Weil   ceph: rename rsiz...
811
812
  	/* set ra_pages based on rasize mount option? */
  	if (fsc->mount_options->rasize >= PAGE_CACHE_SIZE)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
813
  		fsc->backing_dev_info.ra_pages =
83817e35c   Sage Weil   ceph: rename rsiz...
814
  			(fsc->mount_options->rasize + PAGE_CACHE_SIZE - 1)
16725b9d2   Sage Weil   ceph: super.c
815
  			>> PAGE_SHIFT;
e98522274   Yehuda Sadeh   ceph: set up read...
816
817
818
  	else
  		fsc->backing_dev_info.ra_pages =
  			default_backing_dev_info.ra_pages;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
819
  	err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
31e0cf8f6   Sage Weil   ceph: name bdi ce...
820
  			   atomic_long_inc_return(&bdi_seq));
5dfc589a8   Sage Weil   ceph: unregister ...
821
  	if (!err)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
822
  		sb->s_bdi = &fsc->backing_dev_info;
16725b9d2   Sage Weil   ceph: super.c
823
824
  	return err;
  }
a7f9fb205   Al Viro   convert ceph
825
826
  static struct dentry *ceph_mount(struct file_system_type *fs_type,
  		       int flags, const char *dev_name, void *data)
16725b9d2   Sage Weil   ceph: super.c
827
828
  {
  	struct super_block *sb;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
829
  	struct ceph_fs_client *fsc;
a7f9fb205   Al Viro   convert ceph
830
  	struct dentry *res;
16725b9d2   Sage Weil   ceph: super.c
831
832
  	int err;
  	int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
6a18be16f   Sage Weil   ceph: fix sparse ...
833
  	const char *path = NULL;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
834
835
  	struct ceph_mount_options *fsopt = NULL;
  	struct ceph_options *opt = NULL;
16725b9d2   Sage Weil   ceph: super.c
836

a7f9fb205   Al Viro   convert ceph
837
838
  	dout("ceph_mount
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
839
  	err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
a7f9fb205   Al Viro   convert ceph
840
841
  	if (err < 0) {
  		res = ERR_PTR(err);
6b8051855   Sage Weil   ceph: allocate an...
842
  		goto out_final;
a7f9fb205   Al Viro   convert ceph
843
  	}
16725b9d2   Sage Weil   ceph: super.c
844
845
  
  	/* create client (which we may/may not use) */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
846
847
  	fsc = create_fs_client(fsopt, opt);
  	if (IS_ERR(fsc)) {
a7f9fb205   Al Viro   convert ceph
848
  		res = ERR_CAST(fsc);
259a187ad   Noah Watkins   ceph: fix memory ...
849
850
  		destroy_mount_options(fsopt);
  		ceph_destroy_options(opt);
6b8051855   Sage Weil   ceph: allocate an...
851
852
  		goto out_final;
  	}
16725b9d2   Sage Weil   ceph: super.c
853

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
854
  	err = ceph_mdsc_init(fsc);
a7f9fb205   Al Viro   convert ceph
855
856
  	if (err < 0) {
  		res = ERR_PTR(err);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
857
  		goto out;
a7f9fb205   Al Viro   convert ceph
858
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
859
860
  
  	if (ceph_test_opt(fsc->client, NOSHARE))
16725b9d2   Sage Weil   ceph: super.c
861
  		compare_super = NULL;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
862
  	sb = sget(fs_type, compare_super, ceph_set_super, fsc);
16725b9d2   Sage Weil   ceph: super.c
863
  	if (IS_ERR(sb)) {
a7f9fb205   Al Viro   convert ceph
864
  		res = ERR_CAST(sb);
16725b9d2   Sage Weil   ceph: super.c
865
866
  		goto out;
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
867
868
869
870
871
872
  	if (ceph_sb_to_client(sb) != fsc) {
  		ceph_mdsc_destroy(fsc);
  		destroy_fs_client(fsc);
  		fsc = ceph_sb_to_client(sb);
  		dout("get_sb got existing client %p
  ", fsc);
16725b9d2   Sage Weil   ceph: super.c
873
  	} else {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
874
875
876
  		dout("get_sb using new client %p
  ", fsc);
  		err = ceph_register_bdi(sb, fsc);
a7f9fb205   Al Viro   convert ceph
877
878
  		if (err < 0) {
  			res = ERR_PTR(err);
16725b9d2   Sage Weil   ceph: super.c
879
  			goto out_splat;
a7f9fb205   Al Viro   convert ceph
880
  		}
16725b9d2   Sage Weil   ceph: super.c
881
  	}
a7f9fb205   Al Viro   convert ceph
882
883
  	res = ceph_real_mount(fsc, path);
  	if (IS_ERR(res))
16725b9d2   Sage Weil   ceph: super.c
884
  		goto out_splat;
a7f9fb205   Al Viro   convert ceph
885
886
887
888
  	dout("root %p inode %p ino %llx.%llx
  ", res,
  	     res->d_inode, ceph_vinop(res->d_inode));
  	return res;
16725b9d2   Sage Weil   ceph: super.c
889
890
  
  out_splat:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
891
  	ceph_mdsc_close_sessions(fsc->mdsc);
3981f2e2a   Al Viro   ceph: should use ...
892
  	deactivate_locked_super(sb);
16725b9d2   Sage Weil   ceph: super.c
893
894
895
  	goto out_final;
  
  out:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
896
897
  	ceph_mdsc_destroy(fsc);
  	destroy_fs_client(fsc);
16725b9d2   Sage Weil   ceph: super.c
898
  out_final:
a7f9fb205   Al Viro   convert ceph
899
900
901
  	dout("ceph_mount fail %ld
  ", PTR_ERR(res));
  	return res;
16725b9d2   Sage Weil   ceph: super.c
902
903
904
905
  }
  
  static void ceph_kill_sb(struct super_block *s)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
906
  	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
16725b9d2   Sage Weil   ceph: super.c
907
908
  	dout("kill_sb %p
  ", s);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
909
  	ceph_mdsc_pre_umount(fsc->mdsc);
16725b9d2   Sage Weil   ceph: super.c
910
  	kill_anon_super(s);    /* will call put_super after sb is r/o */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
911
912
  	ceph_mdsc_destroy(fsc);
  	destroy_fs_client(fsc);
16725b9d2   Sage Weil   ceph: super.c
913
914
915
916
917
  }
  
  static struct file_system_type ceph_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ceph",
a7f9fb205   Al Viro   convert ceph
918
  	.mount		= ceph_mount,
16725b9d2   Sage Weil   ceph: super.c
919
920
921
922
923
924
925
926
927
  	.kill_sb	= ceph_kill_sb,
  	.fs_flags	= FS_RENAME_DOES_D_MOVE,
  };
  
  #define _STRINGIFY(x) #x
  #define STRINGIFY(x) _STRINGIFY(x)
  
  static int __init init_ceph(void)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
928
  	int ret = init_caches();
16725b9d2   Sage Weil   ceph: super.c
929
  	if (ret)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
930
  		goto out;
16725b9d2   Sage Weil   ceph: super.c
931

16725b9d2   Sage Weil   ceph: super.c
932
933
934
  	ret = register_filesystem(&ceph_fs_type);
  	if (ret)
  		goto out_icache;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
935
936
  	pr_info("loaded (mds proto %d)
  ", CEPH_MDSC_PROTOCOL);
16725b9d2   Sage Weil   ceph: super.c
937
938
939
940
  	return 0;
  
  out_icache:
  	destroy_caches();
16725b9d2   Sage Weil   ceph: super.c
941
942
943
944
945
946
947
948
949
  out:
  	return ret;
  }
  
  static void __exit exit_ceph(void)
  {
  	dout("exit_ceph
  ");
  	unregister_filesystem(&ceph_fs_type);
16725b9d2   Sage Weil   ceph: super.c
950
  	destroy_caches();
16725b9d2   Sage Weil   ceph: super.c
951
952
953
954
955
956
957
958
959
960
  }
  
  module_init(init_ceph);
  module_exit(exit_ceph);
  
  MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
  MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
  MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
  MODULE_DESCRIPTION("Ceph filesystem for Linux");
  MODULE_LICENSE("GPL");