Blame view

fs/ceph/super.c 25.4 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
  #include "mds_client.h"
99ccbd229   Milosz Tanski   ceph: use fscache...
20
  #include "cache.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
21

1fe60e51a   Sage Weil   libceph: move fea...
22
  #include <linux/ceph/ceph_features.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
23
24
25
26
  #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
27
28
29
30
31
32
  
  /*
   * Ceph superblock operations
   *
   * Handle the basics of mounting, unmounting.
   */
16725b9d2   Sage Weil   ceph: super.c
33
34
35
36
37
  /*
   * super ops
   */
  static void ceph_put_super(struct super_block *s)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
38
  	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
16725b9d2   Sage Weil   ceph: super.c
39
40
41
  
  	dout("put_super
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
42
  	ceph_mdsc_close_sessions(fsc->mdsc);
16725b9d2   Sage Weil   ceph: super.c
43
44
45
46
  }
  
  static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
2b0143b5c   David Howells   VFS: normal files...
47
  	struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
48
  	struct ceph_monmap *monmap = fsc->client->monc.monmap;
16725b9d2   Sage Weil   ceph: super.c
49
50
51
52
53
54
  	struct ceph_statfs st;
  	u64 fsid;
  	int err;
  
  	dout("statfs
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
55
  	err = ceph_monc_do_statfs(&fsc->client->monc, &st);
16725b9d2   Sage Weil   ceph: super.c
56
57
58
59
60
61
62
63
64
  	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.
92a49fb0f   Sage Weil   ceph: fix statvfs...
65
66
67
68
69
  	 *
  	 * NOTE: for the time being, we make bsize == frsize to humor
  	 * not-yet-ancient versions of glibc that are broken.
  	 * Someday, we will probably want to report a real block
  	 * size...  whatever that may mean for a network file system!
16725b9d2   Sage Weil   ceph: super.c
70
71
  	 */
  	buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
92a49fb0f   Sage Weil   ceph: fix statvfs...
72
  	buf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
16725b9d2   Sage Weil   ceph: super.c
73
  	buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
8f04d4227   Greg Farnum   ceph: report f_bf...
74
  	buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
16725b9d2   Sage Weil   ceph: super.c
75
76
77
78
  	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...
79
  	buf->f_namelen = NAME_MAX;
16725b9d2   Sage Weil   ceph: super.c
80
81
82
83
84
85
86
87
  
  	/* 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...
88
  static int ceph_sync_fs(struct super_block *sb, int wait)
16725b9d2   Sage Weil   ceph: super.c
89
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
90
  	struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
2d9c98ae9   Sage Weil   ceph: make ->sync...
91
92
93
94
  
  	if (!wait) {
  		dout("sync_fs (non-blocking)
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
95
  		ceph_flush_dirty_caps(fsc->mdsc);
2d9c98ae9   Sage Weil   ceph: make ->sync...
96
97
98
99
100
101
102
  		dout("sync_fs (non-blocking) done
  ");
  		return 0;
  	}
  
  	dout("sync_fs (blocking)
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
103
104
  	ceph_osdc_sync(&fsc->client->osdc);
  	ceph_mdsc_sync(fsc->mdsc);
2d9c98ae9   Sage Weil   ceph: make ->sync...
105
106
  	dout("sync_fs (blocking) done
  ");
16725b9d2   Sage Weil   ceph: super.c
107
108
  	return 0;
  }
16725b9d2   Sage Weil   ceph: super.c
109
110
111
112
  /*
   * mount options
   */
  enum {
16725b9d2   Sage Weil   ceph: super.c
113
114
  	Opt_wsize,
  	Opt_rsize,
83817e35c   Sage Weil   ceph: rename rsiz...
115
  	Opt_rasize,
16725b9d2   Sage Weil   ceph: super.c
116
117
  	Opt_caps_wanted_delay_min,
  	Opt_caps_wanted_delay_max,
6e19a16ef   Sage Weil   ceph: clean up mo...
118
  	Opt_cap_release_safety,
16725b9d2   Sage Weil   ceph: super.c
119
  	Opt_readdir_max_entries,
23804d91f   Sage Weil   ceph: specify max...
120
  	Opt_readdir_max_bytes,
2baba2501   Yehuda Sadeh   ceph: writeback c...
121
  	Opt_congestion_kb,
e53c2fe07   Sage Weil   ceph: fix, clean ...
122
  	Opt_last_int,
16725b9d2   Sage Weil   ceph: super.c
123
124
  	/* int args above */
  	Opt_snapdirname,
e53c2fe07   Sage Weil   ceph: fix, clean ...
125
  	Opt_last_string,
16725b9d2   Sage Weil   ceph: super.c
126
  	/* string args above */
16725b9d2   Sage Weil   ceph: super.c
127
128
129
130
  	Opt_dirstat,
  	Opt_nodirstat,
  	Opt_rbytes,
  	Opt_norbytes,
cffaba15c   Alex Elder   ceph: ensure Bool...
131
  	Opt_asyncreaddir,
16725b9d2   Sage Weil   ceph: super.c
132
  	Opt_noasyncreaddir,
a40dc6cc2   Sage Weil   ceph: enable/disa...
133
134
  	Opt_dcache,
  	Opt_nodcache,
ad1fee96c   Yehuda Sadeh   ceph: add ino32 m...
135
  	Opt_ino32,
cffaba15c   Alex Elder   ceph: ensure Bool...
136
  	Opt_noino32,
99ccbd229   Milosz Tanski   ceph: use fscache...
137
  	Opt_fscache,
45195e42c   Sage Weil   ceph: add acl, no...
138
  	Opt_nofscache,
10183a695   Yan, Zheng   ceph: check OSD c...
139
140
  	Opt_poolperm,
  	Opt_nopoolperm,
45195e42c   Sage Weil   ceph: add acl, no...
141
142
143
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	Opt_acl,
  #endif
10183a695   Yan, Zheng   ceph: check OSD c...
144
  	Opt_noacl,
16725b9d2   Sage Weil   ceph: super.c
145
  };
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
146
  static match_table_t fsopt_tokens = {
16725b9d2   Sage Weil   ceph: super.c
147
148
  	{Opt_wsize, "wsize=%d"},
  	{Opt_rsize, "rsize=%d"},
83817e35c   Sage Weil   ceph: rename rsiz...
149
  	{Opt_rasize, "rasize=%d"},
16725b9d2   Sage Weil   ceph: super.c
150
151
  	{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...
152
  	{Opt_cap_release_safety, "cap_release_safety=%d"},
16725b9d2   Sage Weil   ceph: super.c
153
  	{Opt_readdir_max_entries, "readdir_max_entries=%d"},
23804d91f   Sage Weil   ceph: specify max...
154
  	{Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
2baba2501   Yehuda Sadeh   ceph: writeback c...
155
  	{Opt_congestion_kb, "write_congestion_kb=%d"},
16725b9d2   Sage Weil   ceph: super.c
156
157
  	/* int args above */
  	{Opt_snapdirname, "snapdirname=%s"},
16725b9d2   Sage Weil   ceph: super.c
158
  	/* string args above */
16725b9d2   Sage Weil   ceph: super.c
159
160
161
162
  	{Opt_dirstat, "dirstat"},
  	{Opt_nodirstat, "nodirstat"},
  	{Opt_rbytes, "rbytes"},
  	{Opt_norbytes, "norbytes"},
cffaba15c   Alex Elder   ceph: ensure Bool...
163
  	{Opt_asyncreaddir, "asyncreaddir"},
16725b9d2   Sage Weil   ceph: super.c
164
  	{Opt_noasyncreaddir, "noasyncreaddir"},
a40dc6cc2   Sage Weil   ceph: enable/disa...
165
166
  	{Opt_dcache, "dcache"},
  	{Opt_nodcache, "nodcache"},
ad1fee96c   Yehuda Sadeh   ceph: add ino32 m...
167
  	{Opt_ino32, "ino32"},
cffaba15c   Alex Elder   ceph: ensure Bool...
168
  	{Opt_noino32, "noino32"},
99ccbd229   Milosz Tanski   ceph: use fscache...
169
170
  	{Opt_fscache, "fsc"},
  	{Opt_nofscache, "nofsc"},
10183a695   Yan, Zheng   ceph: check OSD c...
171
172
  	{Opt_poolperm, "poolperm"},
  	{Opt_nopoolperm, "nopoolperm"},
45195e42c   Sage Weil   ceph: add acl, no...
173
174
175
176
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	{Opt_acl, "acl"},
  #endif
  	{Opt_noacl, "noacl"},
16725b9d2   Sage Weil   ceph: super.c
177
178
  	{-1, NULL}
  };
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
179
  static int parse_fsopt_token(char *c, void *private)
c309f0ab2   Sage Weil   ceph: clean up fs...
180
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  	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...
196
  		}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
197
198
199
200
201
202
203
204
205
  		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...
206
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  	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...
224
225
226
  	case Opt_rasize:
  		fsopt->rasize = intval;
  		break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  	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;
cffaba15c   Alex Elder   ceph: ensure Bool...
254
255
256
  	case Opt_asyncreaddir:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR;
  		break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
257
258
259
  	case Opt_noasyncreaddir:
  		fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
  		break;
a40dc6cc2   Sage Weil   ceph: enable/disa...
260
261
262
263
264
265
  	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...
266
267
268
  	case Opt_ino32:
  		fsopt->flags |= CEPH_MOUNT_OPT_INO32;
  		break;
cffaba15c   Alex Elder   ceph: ensure Bool...
269
270
271
  	case Opt_noino32:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
  		break;
99ccbd229   Milosz Tanski   ceph: use fscache...
272
273
274
275
276
277
  	case Opt_fscache:
  		fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
  		break;
  	case Opt_nofscache:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
  		break;
10183a695   Yan, Zheng   ceph: check OSD c...
278
279
280
281
282
283
284
  	case Opt_poolperm:
  		fsopt->flags &= ~CEPH_MOUNT_OPT_NOPOOLPERM;
  		printk ("pool perm");
  		break;
  	case Opt_nopoolperm:
  		fsopt->flags |= CEPH_MOUNT_OPT_NOPOOLPERM;
  		break;
45195e42c   Sage Weil   ceph: add acl, no...
285
286
287
288
289
290
291
292
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	case Opt_acl:
  		fsopt->sb_flags |= MS_POSIXACL;
  		break;
  #endif
  	case Opt_noacl:
  		fsopt->sb_flags &= ~MS_POSIXACL;
  		break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
293
294
295
296
  	default:
  		BUG_ON(token);
  	}
  	return 0;
c309f0ab2   Sage Weil   ceph: clean up fs...
297
  }
16725b9d2   Sage Weil   ceph: super.c
298

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
299
  static void destroy_mount_options(struct ceph_mount_options *args)
16725b9d2   Sage Weil   ceph: super.c
300
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
301
302
303
304
305
  	dout("destroy_mount_options %p
  ", args);
  	kfree(args->snapdir_name);
  	kfree(args);
  }
16725b9d2   Sage Weil   ceph: super.c
306

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
307
308
309
310
311
312
313
314
315
316
  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
317

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
318
319
320
321
322
323
324
325
  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
326

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  	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;
c98f533c9   Alex Elder   ceph: let path po...
346
347
348
349
  	int err;
  
  	if (!dev_name || !*dev_name)
  		return -EINVAL;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
350
351
352
353
354
355
356
  
  	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...
357
358
  	fsopt->sb_flags = flags;
  	fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
359

80db8bea6   Noah Watkins   ceph: replace lea...
360
361
362
  	fsopt->rsize = CEPH_RSIZE_DEFAULT;
  	fsopt->rasize = CEPH_RASIZE_DEFAULT;
  	fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
a149bb9a2   Sanidhya Kashyap   ceph: kstrdup() m...
363
364
365
366
  	if (!fsopt->snapdir_name) {
  		err = -ENOMEM;
  		goto out;
  	}
50aac4fec   Sage Weil   ceph: fix cap_wan...
367
368
  	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...
369
370
371
372
  	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();
c98f533c9   Alex Elder   ceph: let path po...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  	/*
  	 * Distinguish the server list from the path in "dev_name".
  	 * Internally we do not include the leading '/' in the path.
  	 *
  	 * "dev_name" will look like:
  	 *     <server_spec>[,<server_spec>...]:[<path>]
  	 * where
  	 *     <server_spec> is <ip>[:<port>]
  	 *     <path> is optional, but if present must begin with '/'
  	 */
  	dev_name_end = strchr(dev_name, '/');
  	if (dev_name_end) {
  		/* skip over leading '/' for path */
  		*path = dev_name_end + 1;
  	} else {
  		/* path is empty */
  		dev_name_end = dev_name + strlen(dev_name);
  		*path = dev_name_end;
  	}
80db8bea6   Noah Watkins   ceph: replace lea...
392
  	err = -EINVAL;
c98f533c9   Alex Elder   ceph: let path po...
393
  	dev_name_end--;		/* back up to ':' separator */
544642963   Sasha Levin   ceph: avoid acces...
394
  	if (dev_name_end < dev_name || *dev_name_end != ':') {
c98f533c9   Alex Elder   ceph: let path po...
395
396
  		pr_err("device name is missing path (no : separator in %s)
  ",
80db8bea6   Noah Watkins   ceph: replace lea...
397
398
399
  				dev_name);
  		goto out;
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
400
401
  	dout("device name '%.*s'
  ", (int)(dev_name_end - dev_name), dev_name);
16725b9d2   Sage Weil   ceph: super.c
402
403
  	dout("server path '%s'
  ", *path);
ee57741c5   Alex Elder   rbd: make ceph_pa...
404
  	*popt = ceph_parse_options(options, dev_name, dev_name_end,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
405
  				 parse_fsopt_token, (void *)fsopt);
ee57741c5   Alex Elder   rbd: make ceph_pa...
406
407
  	if (IS_ERR(*popt)) {
  		err = PTR_ERR(*popt);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
408
  		goto out;
ee57741c5   Alex Elder   rbd: make ceph_pa...
409
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
410
411
412
413
  
  	/* success */
  	*pfsopt = fsopt;
  	return 0;
16725b9d2   Sage Weil   ceph: super.c
414

7b813c460   Sage Weil   ceph: reduce pars...
415
  out:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
416
417
  	destroy_mount_options(fsopt);
  	return err;
16725b9d2   Sage Weil   ceph: super.c
418
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
419
420
421
  /**
   * ceph_show_options - Show mount options in /proc/mounts
   * @m: seq_file to write to
34c80b1d9   Al Viro   vfs: switch ->sho...
422
   * @root: root of that (sub)tree
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
423
   */
34c80b1d9   Al Viro   vfs: switch ->sho...
424
  static int ceph_show_options(struct seq_file *m, struct dentry *root)
16725b9d2   Sage Weil   ceph: super.c
425
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
426
  	struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
427
  	struct ceph_mount_options *fsopt = fsc->mount_options;
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  	size_t pos;
  	int ret;
  
  	/* a comma between MNT/MS and client options */
  	seq_putc(m, ',');
  	pos = m->count;
  
  	ret = ceph_print_client_options(m, fsc->client);
  	if (ret)
  		return ret;
  
  	/* retract our comma if no client options */
  	if (m->count == pos)
  		m->count--;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
442
443
444
  
  	if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
  		seq_puts(m, ",dirstat");
133e91566   Yan, Zheng   ceph: don't enabl...
445
446
  	if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES))
  		seq_puts(m, ",rbytes");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
447
448
  	if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
  		seq_puts(m, ",noasyncreaddir");
ff7eeb82c   Ilya Dryomov   ceph: show non-de...
449
  	if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0)
a40dc6cc2   Sage Weil   ceph: enable/disa...
450
  		seq_puts(m, ",nodcache");
99ccbd229   Milosz Tanski   ceph: use fscache...
451
452
  	if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE)
  		seq_puts(m, ",fsc");
10183a695   Yan, Zheng   ceph: check OSD c...
453
454
  	if (fsopt->flags & CEPH_MOUNT_OPT_NOPOOLPERM)
  		seq_puts(m, ",nopoolperm");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
455

45195e42c   Sage Weil   ceph: add acl, no...
456
457
458
459
460
461
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	if (fsopt->sb_flags & MS_POSIXACL)
  		seq_puts(m, ",acl");
  	else
  		seq_puts(m, ",noacl");
  #endif
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
462
463
  	if (fsopt->wsize)
  		seq_printf(m, ",wsize=%d", fsopt->wsize);
80456f867   Sage Weil   ceph: move readah...
464
  	if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
465
  		seq_printf(m, ",rsize=%d", fsopt->rsize);
83817e35c   Sage Weil   ceph: rename rsiz...
466
  	if (fsopt->rasize != CEPH_RASIZE_DEFAULT)
2151937d7   Sage Weil   ceph: fix rasize ...
467
  		seq_printf(m, ",rasize=%d", fsopt->rasize);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  	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))
a068acf2e   Kees Cook   fs: create and us...
484
  		seq_show_option(m, "snapdirname", fsopt->snapdir_name);
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
485

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
486
  	return 0;
16725b9d2   Sage Weil   ceph: super.c
487
488
489
  }
  
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
490
491
   * handle any mon messages the standard library doesn't understand.
   * return error if we don't either.
16725b9d2   Sage Weil   ceph: super.c
492
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
493
  static int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg)
16725b9d2   Sage Weil   ceph: super.c
494
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  	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...
511
  static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
512
513
514
  					struct ceph_options *opt)
  {
  	struct ceph_fs_client *fsc;
12b4629a9   Ilya Dryomov   libceph: all feat...
515
  	const u64 supported_features =
6ab00d465   Sage Weil   libceph: create m...
516
  		CEPH_FEATURE_FLOCK |
65a22662b   Yan, Zheng   ceph: support inl...
517
518
  		CEPH_FEATURE_DIRLAYOUTHASH |
  		CEPH_FEATURE_MDS_INLINE_DATA;
12b4629a9   Ilya Dryomov   libceph: all feat...
519
  	const u64 required_features = 0;
3bf53337a   Alex Elder   ceph: set up page...
520
521
  	int page_count;
  	size_t size;
16725b9d2   Sage Weil   ceph: super.c
522
  	int err = -ENOMEM;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
523
524
  	fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
  	if (!fsc)
16725b9d2   Sage Weil   ceph: super.c
525
  		return ERR_PTR(-ENOMEM);
6ab00d465   Sage Weil   libceph: create m...
526
527
  	fsc->client = ceph_create_client(opt, fsc, supported_features,
  					 required_features);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
528
529
530
531
532
  	if (IS_ERR(fsc->client)) {
  		err = PTR_ERR(fsc->client);
  		goto fail;
  	}
  	fsc->client->extra_mon_dispatch = extra_mon_dispatch;
82dcabad7   Ilya Dryomov   libceph: revamp s...
533
  	ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP, 0, true);
16725b9d2   Sage Weil   ceph: super.c
534

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

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

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

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

16725b9d2   Sage Weil   ceph: super.c
546
  	err = -ENOMEM;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
547
548
549
550
551
  	/*
  	 * 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 ...
552
  	if (fsc->wb_wq == NULL)
859e7b149   Sage Weil   ceph: init/destro...
553
  		goto fail_bdi;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
554
  	fsc->pg_inv_wq = alloc_workqueue("ceph-pg-invalid", 0, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
555
  	if (fsc->pg_inv_wq == NULL)
16725b9d2   Sage Weil   ceph: super.c
556
  		goto fail_wb_wq;
01e6acc4e   Tejun Heo   ceph: fsc->*_wq's...
557
  	fsc->trunc_wq = alloc_workqueue("ceph-trunc", 0, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
558
  	if (fsc->trunc_wq == NULL)
16725b9d2   Sage Weil   ceph: super.c
559
  		goto fail_pg_inv_wq;
b9bfb93ce   Sage Weil   ceph: move mempoo...
560
561
  	/* set up mempools */
  	err = -ENOMEM;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
562
  	page_count = fsc->mount_options->wsize >> PAGE_SHIFT;
3bf53337a   Alex Elder   ceph: set up page...
563
564
  	size = sizeof (struct page *) * (page_count ? page_count : 1);
  	fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10, size);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
565
  	if (!fsc->wb_pagevec_pool)
b9bfb93ce   Sage Weil   ceph: move mempoo...
566
  		goto fail_trunc_wq;
99ccbd229   Milosz Tanski   ceph: use fscache...
567
568
569
570
  	/* setup fscache */
  	if ((fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) &&
  	    (ceph_fscache_register_fs(fsc) != 0))
  		goto fail_fscache;
85ccce43a   Sage Weil   ceph: clean up re...
571
  	/* caps */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
572
573
574
  	fsc->min_caps = fsopt->max_readdir;
  
  	return fsc;
b9bfb93ce   Sage Weil   ceph: move mempoo...
575

99ccbd229   Milosz Tanski   ceph: use fscache...
576
577
  fail_fscache:
  	ceph_fscache_unregister_fs(fsc);
16725b9d2   Sage Weil   ceph: super.c
578
  fail_trunc_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
579
  	destroy_workqueue(fsc->trunc_wq);
16725b9d2   Sage Weil   ceph: super.c
580
  fail_pg_inv_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
581
  	destroy_workqueue(fsc->pg_inv_wq);
16725b9d2   Sage Weil   ceph: super.c
582
  fail_wb_wq:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
583
  	destroy_workqueue(fsc->wb_wq);
859e7b149   Sage Weil   ceph: init/destro...
584
  fail_bdi:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
585
586
587
  	bdi_destroy(&fsc->backing_dev_info);
  fail_client:
  	ceph_destroy_client(fsc->client);
16725b9d2   Sage Weil   ceph: super.c
588
  fail:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
589
  	kfree(fsc);
16725b9d2   Sage Weil   ceph: super.c
590
591
  	return ERR_PTR(err);
  }
0c6d4b4e2   H Hartley Sweeten   ceph/super.c: qui...
592
  static void destroy_fs_client(struct ceph_fs_client *fsc)
16725b9d2   Sage Weil   ceph: super.c
593
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
594
595
  	dout("destroy_fs_client %p
  ", fsc);
16725b9d2   Sage Weil   ceph: super.c
596

99ccbd229   Milosz Tanski   ceph: use fscache...
597
  	ceph_fscache_unregister_fs(fsc);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
598
599
600
  	destroy_workqueue(fsc->wb_wq);
  	destroy_workqueue(fsc->pg_inv_wq);
  	destroy_workqueue(fsc->trunc_wq);
16725b9d2   Sage Weil   ceph: super.c
601

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

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

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

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

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

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
612
613
614
  	kfree(fsc);
  	dout("destroy_fs_client %p done
  ", fsc);
16725b9d2   Sage Weil   ceph: super.c
615
616
617
  }
  
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
618
   * caches
0743304d8   Sage Weil   ceph: fix debugfs...
619
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
620
621
  struct kmem_cache *ceph_inode_cachep;
  struct kmem_cache *ceph_cap_cachep;
f66fd9f09   Yan, Zheng   ceph: pre-allocat...
622
  struct kmem_cache *ceph_cap_flush_cachep;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
623
624
625
626
  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...
627
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
628
629
630
631
632
633
  	struct ceph_inode_info *ci = foo;
  	inode_init_once(&ci->vfs_inode);
  }
  
  static int __init init_caches(void)
  {
99ccbd229   Milosz Tanski   ceph: use fscache...
634
  	int error = -ENOMEM;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
635
636
637
  	ceph_inode_cachep = kmem_cache_create("ceph_inode_info",
  				      sizeof(struct ceph_inode_info),
  				      __alignof__(struct ceph_inode_info),
5d097056c   Vladimir Davydov   kmemcg: account c...
638
639
  				      SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
  				      SLAB_ACCOUNT, ceph_inode_init_once);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
640
641
642
643
644
645
646
  	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;
f66fd9f09   Yan, Zheng   ceph: pre-allocat...
647
648
649
650
  	ceph_cap_flush_cachep = KMEM_CACHE(ceph_cap_flush,
  					   SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
  	if (ceph_cap_flush_cachep == NULL)
  		goto bad_cap_flush;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
651
652
653
654
655
656
657
658
659
660
  
  	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;
99ccbd229   Milosz Tanski   ceph: use fscache...
661
662
  	if ((error = ceph_fscache_register()))
  		goto bad_file;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
663

99ccbd229   Milosz Tanski   ceph: use fscache...
664
  	return 0;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
665
666
667
  bad_file:
  	kmem_cache_destroy(ceph_dentry_cachep);
  bad_dentry:
f66fd9f09   Yan, Zheng   ceph: pre-allocat...
668
669
  	kmem_cache_destroy(ceph_cap_flush_cachep);
  bad_cap_flush:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
670
671
672
  	kmem_cache_destroy(ceph_cap_cachep);
  bad_cap:
  	kmem_cache_destroy(ceph_inode_cachep);
99ccbd229   Milosz Tanski   ceph: use fscache...
673
  	return error;
0743304d8   Sage Weil   ceph: fix debugfs...
674
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
675
676
  static void destroy_caches(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
677
678
679
680
681
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
99ccbd229   Milosz Tanski   ceph: use fscache...
682

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
683
684
  	kmem_cache_destroy(ceph_inode_cachep);
  	kmem_cache_destroy(ceph_cap_cachep);
f66fd9f09   Yan, Zheng   ceph: pre-allocat...
685
  	kmem_cache_destroy(ceph_cap_flush_cachep);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
686
687
  	kmem_cache_destroy(ceph_dentry_cachep);
  	kmem_cache_destroy(ceph_file_cachep);
99ccbd229   Milosz Tanski   ceph: use fscache...
688
689
  
  	ceph_fscache_unregister();
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
690
  }
0743304d8   Sage Weil   ceph: fix debugfs...
691
  /*
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
692
693
   * 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
694
   */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
695
  static void ceph_umount_begin(struct super_block *sb)
16725b9d2   Sage Weil   ceph: super.c
696
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
697
698
699
700
701
702
703
  	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;
48fec5d0a   Yan, Zheng   ceph: EIO all ope...
704
  	ceph_mdsc_force_umount(fsc->mdsc);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
705
  	return;
16725b9d2   Sage Weil   ceph: super.c
706
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
707
708
709
710
  static const struct super_operations ceph_super_ops = {
  	.alloc_inode	= ceph_alloc_inode,
  	.destroy_inode	= ceph_destroy_inode,
  	.write_inode    = ceph_write_inode,
9f12bd119   Yan, Zheng   ceph: drop unconn...
711
  	.drop_inode	= ceph_drop_inode,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
712
713
714
715
716
717
  	.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
718
719
720
721
  /*
   * 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 ...
722
  static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
16725b9d2   Sage Weil   ceph: super.c
723
724
725
  				       const char *path,
  				       unsigned long started)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
726
  	struct ceph_mds_client *mdsc = fsc->mdsc;
16725b9d2   Sage Weil   ceph: super.c
727
728
729
730
731
732
733
734
735
  	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_...
736
  		return ERR_CAST(req);
16725b9d2   Sage Weil   ceph: super.c
737
  	req->r_path1 = kstrdup(path, GFP_NOFS);
a149bb9a2   Sanidhya Kashyap   ceph: kstrdup() m...
738
739
740
741
  	if (!req->r_path1) {
  		root = ERR_PTR(-ENOMEM);
  		goto out;
  	}
16725b9d2   Sage Weil   ceph: super.c
742
743
744
  	req->r_ino1.ino = CEPH_INO_ROOT;
  	req->r_ino1.snap = CEPH_NOSNAP;
  	req->r_started = started;
a319bf56a   Ilya Dryomov   libceph: store ti...
745
  	req->r_timeout = fsc->client->options->mount_timeout;
16725b9d2   Sage Weil   ceph: super.c
746
747
748
749
  	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...
750
751
  		struct inode *inode = req->r_target_inode;
  		req->r_target_inode = NULL;
16725b9d2   Sage Weil   ceph: super.c
752
753
  		dout("open_root_inode success
  ");
3c5184ef1   Al Viro   ceph: d_alloc_roo...
754
  		if (ceph_ino(inode) == CEPH_INO_ROOT &&
774ac21da   Sage Weil   ceph: initialize ...
755
  		    fsc->sb->s_root == NULL) {
48fde701a   Al Viro   switch open-coded...
756
  			root = d_make_root(inode);
3c5184ef1   Al Viro   ceph: d_alloc_roo...
757
  			if (!root) {
3c5184ef1   Al Viro   ceph: d_alloc_roo...
758
759
760
  				root = ERR_PTR(-ENOMEM);
  				goto out;
  			}
774ac21da   Sage Weil   ceph: initialize ...
761
  		} else {
1a0a397e4   J. Bruce Fields   dcache: d_obtain_...
762
  			root = d_obtain_root(inode);
774ac21da   Sage Weil   ceph: initialize ...
763
  		}
d46cfba53   Alex Elder   ceph: always init...
764
  		ceph_init_dentry(root);
16725b9d2   Sage Weil   ceph: super.c
765
766
767
768
769
  		dout("open_root_inode success, root dentry is %p
  ", root);
  	} else {
  		root = ERR_PTR(err);
  	}
3c5184ef1   Al Viro   ceph: d_alloc_roo...
770
  out:
16725b9d2   Sage Weil   ceph: super.c
771
772
773
  	ceph_mdsc_put_request(req);
  	return root;
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
774

16725b9d2   Sage Weil   ceph: super.c
775
776
777
  /*
   * mount: join the ceph cluster, and open root directory.
   */
a7f9fb205   Al Viro   convert ceph
778
  static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
16725b9d2   Sage Weil   ceph: super.c
779
780
  		      const char *path)
  {
16725b9d2   Sage Weil   ceph: super.c
781
  	int err;
16725b9d2   Sage Weil   ceph: super.c
782
783
  	unsigned long started = jiffies;  /* note the start time */
  	struct dentry *root;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
784
  	int first = 0;   /* first vfsmount for this super_block */
16725b9d2   Sage Weil   ceph: super.c
785

132ca7e1d   Yan, Zheng   ceph: fix mountin...
786
787
  	dout("mount start %p
  ", fsc);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
788
  	mutex_lock(&fsc->client->mount_mutex);
16725b9d2   Sage Weil   ceph: super.c
789

132ca7e1d   Yan, Zheng   ceph: fix mountin...
790
791
792
793
  	if (!fsc->sb->s_root) {
  		err = __ceph_open_session(fsc->client, started);
  		if (err < 0)
  			goto out;
16725b9d2   Sage Weil   ceph: super.c
794

132ca7e1d   Yan, Zheng   ceph: fix mountin...
795
796
797
798
799
800
801
  		dout("mount opening root
  ");
  		root = open_root_dentry(fsc, "", started);
  		if (IS_ERR(root)) {
  			err = PTR_ERR(root);
  			goto out;
  		}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
802
803
804
805
806
807
808
  		fsc->sb->s_root = root;
  		first = 1;
  
  		err = ceph_fs_debugfs_init(fsc);
  		if (err < 0)
  			goto fail;
  	}
16725b9d2   Sage Weil   ceph: super.c
809
810
  
  	if (path[0] == 0) {
132ca7e1d   Yan, Zheng   ceph: fix mountin...
811
  		root = fsc->sb->s_root;
16725b9d2   Sage Weil   ceph: super.c
812
813
814
815
  		dget(root);
  	} else {
  		dout("mount opening base mountpoint
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
816
  		root = open_root_dentry(fsc, path, started);
16725b9d2   Sage Weil   ceph: super.c
817
818
  		if (IS_ERR(root)) {
  			err = PTR_ERR(root);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
819
  			goto fail;
16725b9d2   Sage Weil   ceph: super.c
820
821
  		}
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
822
  	fsc->mount_state = CEPH_MOUNT_MOUNTED;
16725b9d2   Sage Weil   ceph: super.c
823
824
  	dout("mount success
  ");
a7f9fb205   Al Viro   convert ceph
825
826
  	mutex_unlock(&fsc->client->mount_mutex);
  	return root;
16725b9d2   Sage Weil   ceph: super.c
827

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
828
829
830
831
832
  fail:
  	if (first) {
  		dput(fsc->sb->s_root);
  		fsc->sb->s_root = NULL;
  	}
132ca7e1d   Yan, Zheng   ceph: fix mountin...
833
834
835
  out:
  	mutex_unlock(&fsc->client->mount_mutex);
  	return ERR_PTR(err);
16725b9d2   Sage Weil   ceph: super.c
836
837
838
839
  }
  
  static int ceph_set_super(struct super_block *s, void *data)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
840
  	struct ceph_fs_client *fsc = data;
16725b9d2   Sage Weil   ceph: super.c
841
842
843
844
  	int ret;
  
  	dout("set_super %p data %p
  ", s, data);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
845
  	s->s_flags = fsc->mount_options->sb_flags;
16725b9d2   Sage Weil   ceph: super.c
846
  	s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
7221fe4c2   Guangliang Zhao   ceph: add acl for...
847
  	s->s_xattr = ceph_xattr_handlers;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
848
849
  	s->s_fs_info = fsc;
  	fsc->sb = s;
16725b9d2   Sage Weil   ceph: super.c
850
851
852
853
854
855
856
857
858
859
860
861
862
863
  
  	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 ...
864
  	fsc->sb = NULL;
16725b9d2   Sage Weil   ceph: super.c
865
866
867
868
869
870
871
872
  	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 ...
873
874
875
876
  	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
877
878
879
  
  	dout("ceph_compare_super %p
  ", sb);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
880
881
882
883
884
  
  	if (compare_mount_options(fsopt, opt, other)) {
  		dout("monitor(s)/mount options don't match
  ");
  		return 0;
16725b9d2   Sage Weil   ceph: super.c
885
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
886
887
888
889
890
891
892
  	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
893
894
895
896
897
898
899
900
901
902
  		dout("flags differ
  ");
  		return 0;
  	}
  	return 1;
  }
  
  /*
   * construct our own bdi so we can control readahead, etc.
   */
00d5643e7   Jeff Mahoney   ceph: fix atomic6...
903
  static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
31e0cf8f6   Sage Weil   ceph: name bdi ce...
904

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
905
906
  static int ceph_register_bdi(struct super_block *sb,
  			     struct ceph_fs_client *fsc)
16725b9d2   Sage Weil   ceph: super.c
907
908
  {
  	int err;
83817e35c   Sage Weil   ceph: rename rsiz...
909
  	/* set ra_pages based on rasize mount option? */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
910
  	if (fsc->mount_options->rasize >= PAGE_SIZE)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
911
  		fsc->backing_dev_info.ra_pages =
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
912
  			(fsc->mount_options->rasize + PAGE_SIZE - 1)
16725b9d2   Sage Weil   ceph: super.c
913
  			>> PAGE_SHIFT;
e98522274   Yehuda Sadeh   ceph: set up read...
914
915
  	else
  		fsc->backing_dev_info.ra_pages =
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
916
  			VM_MAX_READAHEAD * 1024 / PAGE_SIZE;
e98522274   Yehuda Sadeh   ceph: set up read...
917

d2cc4dde9   Joe Perches   bdi_register: add...
918
  	err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%ld",
31e0cf8f6   Sage Weil   ceph: name bdi ce...
919
  			   atomic_long_inc_return(&bdi_seq));
5dfc589a8   Sage Weil   ceph: unregister ...
920
  	if (!err)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
921
  		sb->s_bdi = &fsc->backing_dev_info;
16725b9d2   Sage Weil   ceph: super.c
922
923
  	return err;
  }
a7f9fb205   Al Viro   convert ceph
924
925
  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
926
927
  {
  	struct super_block *sb;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
928
  	struct ceph_fs_client *fsc;
a7f9fb205   Al Viro   convert ceph
929
  	struct dentry *res;
16725b9d2   Sage Weil   ceph: super.c
930
931
  	int err;
  	int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
6a18be16f   Sage Weil   ceph: fix sparse ...
932
  	const char *path = NULL;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
933
934
  	struct ceph_mount_options *fsopt = NULL;
  	struct ceph_options *opt = NULL;
16725b9d2   Sage Weil   ceph: super.c
935

a7f9fb205   Al Viro   convert ceph
936
937
  	dout("ceph_mount
  ");
45195e42c   Sage Weil   ceph: add acl, no...
938
939
940
941
  
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  	flags |= MS_POSIXACL;
  #endif
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
942
  	err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
a7f9fb205   Al Viro   convert ceph
943
944
  	if (err < 0) {
  		res = ERR_PTR(err);
6b8051855   Sage Weil   ceph: allocate an...
945
  		goto out_final;
a7f9fb205   Al Viro   convert ceph
946
  	}
16725b9d2   Sage Weil   ceph: super.c
947
948
  
  	/* create client (which we may/may not use) */
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
949
950
  	fsc = create_fs_client(fsopt, opt);
  	if (IS_ERR(fsc)) {
a7f9fb205   Al Viro   convert ceph
951
  		res = ERR_CAST(fsc);
259a187ad   Noah Watkins   ceph: fix memory ...
952
953
  		destroy_mount_options(fsopt);
  		ceph_destroy_options(opt);
6b8051855   Sage Weil   ceph: allocate an...
954
955
  		goto out_final;
  	}
16725b9d2   Sage Weil   ceph: super.c
956

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
957
  	err = ceph_mdsc_init(fsc);
a7f9fb205   Al Viro   convert ceph
958
959
  	if (err < 0) {
  		res = ERR_PTR(err);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
960
  		goto out;
a7f9fb205   Al Viro   convert ceph
961
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
962
963
  
  	if (ceph_test_opt(fsc->client, NOSHARE))
16725b9d2   Sage Weil   ceph: super.c
964
  		compare_super = NULL;
9249e17fe   David Howells   VFS: Pass mount f...
965
  	sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc);
16725b9d2   Sage Weil   ceph: super.c
966
  	if (IS_ERR(sb)) {
a7f9fb205   Al Viro   convert ceph
967
  		res = ERR_CAST(sb);
16725b9d2   Sage Weil   ceph: super.c
968
969
  		goto out;
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
970
971
972
973
974
975
  	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
976
  	} else {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
977
978
979
  		dout("get_sb using new client %p
  ", fsc);
  		err = ceph_register_bdi(sb, fsc);
a7f9fb205   Al Viro   convert ceph
980
981
  		if (err < 0) {
  			res = ERR_PTR(err);
16725b9d2   Sage Weil   ceph: super.c
982
  			goto out_splat;
a7f9fb205   Al Viro   convert ceph
983
  		}
16725b9d2   Sage Weil   ceph: super.c
984
  	}
a7f9fb205   Al Viro   convert ceph
985
986
  	res = ceph_real_mount(fsc, path);
  	if (IS_ERR(res))
16725b9d2   Sage Weil   ceph: super.c
987
  		goto out_splat;
a7f9fb205   Al Viro   convert ceph
988
989
  	dout("root %p inode %p ino %llx.%llx
  ", res,
2b0143b5c   David Howells   VFS: normal files...
990
  	     d_inode(res), ceph_vinop(d_inode(res)));
a7f9fb205   Al Viro   convert ceph
991
  	return res;
16725b9d2   Sage Weil   ceph: super.c
992
993
  
  out_splat:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
994
  	ceph_mdsc_close_sessions(fsc->mdsc);
3981f2e2a   Al Viro   ceph: should use ...
995
  	deactivate_locked_super(sb);
16725b9d2   Sage Weil   ceph: super.c
996
997
998
  	goto out_final;
  
  out:
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
999
1000
  	ceph_mdsc_destroy(fsc);
  	destroy_fs_client(fsc);
16725b9d2   Sage Weil   ceph: super.c
1001
  out_final:
a7f9fb205   Al Viro   convert ceph
1002
1003
1004
  	dout("ceph_mount fail %ld
  ", PTR_ERR(res));
  	return res;
16725b9d2   Sage Weil   ceph: super.c
1005
1006
1007
1008
  }
  
  static void ceph_kill_sb(struct super_block *s)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1009
  	struct ceph_fs_client *fsc = ceph_sb_to_client(s);
e4d275090   Christoph Hellwig   ceph: remove call...
1010
  	dev_t dev = s->s_dev;
16725b9d2   Sage Weil   ceph: super.c
1011
1012
  	dout("kill_sb %p
  ", s);
e4d275090   Christoph Hellwig   ceph: remove call...
1013

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1014
  	ceph_mdsc_pre_umount(fsc->mdsc);
e4d275090   Christoph Hellwig   ceph: remove call...
1015
  	generic_shutdown_super(s);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1016
  	ceph_mdsc_destroy(fsc);
e4d275090   Christoph Hellwig   ceph: remove call...
1017

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1018
  	destroy_fs_client(fsc);
e4d275090   Christoph Hellwig   ceph: remove call...
1019
  	free_anon_bdev(dev);
16725b9d2   Sage Weil   ceph: super.c
1020
1021
1022
1023
1024
  }
  
  static struct file_system_type ceph_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ceph",
a7f9fb205   Al Viro   convert ceph
1025
  	.mount		= ceph_mount,
16725b9d2   Sage Weil   ceph: super.c
1026
1027
1028
  	.kill_sb	= ceph_kill_sb,
  	.fs_flags	= FS_RENAME_DOES_D_MOVE,
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
1029
  MODULE_ALIAS_FS("ceph");
16725b9d2   Sage Weil   ceph: super.c
1030

16725b9d2   Sage Weil   ceph: super.c
1031
1032
  static int __init init_ceph(void)
  {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1033
  	int ret = init_caches();
16725b9d2   Sage Weil   ceph: super.c
1034
  	if (ret)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1035
  		goto out;
16725b9d2   Sage Weil   ceph: super.c
1036

eb13e832f   Yan, Zheng   ceph: use fl->fl_...
1037
  	ceph_flock_init();
3ce6cd123   Alex Elder   ceph: avoid repea...
1038
  	ceph_xattr_init();
16725b9d2   Sage Weil   ceph: super.c
1039
1040
  	ret = register_filesystem(&ceph_fs_type);
  	if (ret)
34b759b4a   Ilya Dryomov   ceph: kill ceph_e...
1041
  		goto out_xattr;
16725b9d2   Sage Weil   ceph: super.c
1042

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1043
1044
  	pr_info("loaded (mds proto %d)
  ", CEPH_MDSC_PROTOCOL);
16725b9d2   Sage Weil   ceph: super.c
1045
  	return 0;
97c85a828   Yan, Zheng   ceph: introduce g...
1046
  out_xattr:
3ce6cd123   Alex Elder   ceph: avoid repea...
1047
  	ceph_xattr_exit();
16725b9d2   Sage Weil   ceph: super.c
1048
  	destroy_caches();
16725b9d2   Sage Weil   ceph: super.c
1049
1050
1051
1052
1053
1054
1055
1056
1057
  out:
  	return ret;
  }
  
  static void __exit exit_ceph(void)
  {
  	dout("exit_ceph
  ");
  	unregister_filesystem(&ceph_fs_type);
3ce6cd123   Alex Elder   ceph: avoid repea...
1058
  	ceph_xattr_exit();
16725b9d2   Sage Weil   ceph: super.c
1059
  	destroy_caches();
16725b9d2   Sage Weil   ceph: super.c
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  }
  
  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");