Blame view

fs/exofs/super.c 25.2 KB
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
1
2
  /*
   * Copyright (C) 2005, 2006
27d2e1491   Boaz Harrosh   exofs: Remove IBM...
3
   * Avishay Traeger (avishay@gmail.com)
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
   * Copyright (C) 2008, 2009
   * Boaz Harrosh <bharrosh@panasas.com>
   *
   * Copyrights for code taken from ext2:
   *     Copyright (C) 1992, 1993, 1994, 1995
   *     Remy Card (card@masi.ibp.fr)
   *     Laboratoire MASI - Institut Blaise Pascal
   *     Universite Pierre et Marie Curie (Paris VI)
   *     from
   *     linux/fs/minix/inode.c
   *     Copyright (C) 1991, 1992  Linus Torvalds
   *
   * This file is part of exofs.
   *
   * exofs is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation.  Since it is based on ext2, and the only
   * valid version of GPL for the Linux kernel is version 2, the only valid
   * version of GPL for exofs is version 2.
   *
   * exofs is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with exofs; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   */
  
  #include <linux/string.h>
  #include <linux/parser.h>
  #include <linux/vfs.h>
  #include <linux/random.h>
8cf74b393   Boaz Harrosh   exofs: export_ope...
38
  #include <linux/exportfs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
39
  #include <linux/slab.h>
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
40
41
42
43
44
45
46
47
48
49
50
  
  #include "exofs.h"
  
  /******************************************************************************
   * MOUNT OPTIONS
   *****************************************************************************/
  
  /*
   * struct to hold what we get from mount options
   */
  struct exofs_mountopt {
9ed964843   Boaz Harrosh   exofs: Add option...
51
  	bool is_osdname;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
52
53
54
55
56
57
58
59
  	const char *dev_name;
  	uint64_t pid;
  	int timeout;
  };
  
  /*
   * exofs-specific mount-time options.
   */
9ed964843   Boaz Harrosh   exofs: Add option...
60
  enum { Opt_name, Opt_pid, Opt_to, Opt_err };
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
61
62
63
64
65
66
67
  
  /*
   * Our mount-time options.  These should ideally be 64-bit unsigned, but the
   * kernel's parsing functions do not currently support that.  32-bit should be
   * sufficient for most applications now.
   */
  static match_table_t tokens = {
9ed964843   Boaz Harrosh   exofs: Add option...
68
  	{Opt_name, "osdname=%s"},
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  	{Opt_pid, "pid=%u"},
  	{Opt_to, "to=%u"},
  	{Opt_err, NULL}
  };
  
  /*
   * The main option parsing method.  Also makes sure that all of the mandatory
   * mount options were set.
   */
  static int parse_options(char *options, struct exofs_mountopt *opts)
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
  	bool s_pid = false;
  
  	EXOFS_DBGMSG("parse_options %s
  ", options);
  	/* defaults */
  	memset(opts, 0, sizeof(*opts));
  	opts->timeout = BLK_DEFAULT_SG_TIMEOUT;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		int token;
  		char str[32];
  
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
9ed964843   Boaz Harrosh   exofs: Add option...
100
101
102
103
104
105
106
107
  		case Opt_name:
  			opts->dev_name = match_strdup(&args[0]);
  			if (unlikely(!opts->dev_name)) {
  				EXOFS_ERR("Error allocating dev_name");
  				return -ENOMEM;
  			}
  			opts->is_osdname = true;
  			break;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  		case Opt_pid:
  			if (0 == match_strlcpy(str, &args[0], sizeof(str)))
  				return -EINVAL;
  			opts->pid = simple_strtoull(str, NULL, 0);
  			if (opts->pid < EXOFS_MIN_PID) {
  				EXOFS_ERR("Partition ID must be >= %u",
  					  EXOFS_MIN_PID);
  				return -EINVAL;
  			}
  			s_pid = 1;
  			break;
  		case Opt_to:
  			if (match_int(&args[0], &option))
  				return -EINVAL;
  			if (option <= 0) {
  				EXOFS_ERR("Timout must be > 0");
  				return -EINVAL;
  			}
  			opts->timeout = option * HZ;
  			break;
  		}
  	}
  
  	if (!s_pid) {
  		EXOFS_ERR("Need to specify the following options:
  ");
  		EXOFS_ERR("    -o pid=pid_no_to_use
  ");
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  /******************************************************************************
   * INODE CACHE
   *****************************************************************************/
  
  /*
   * Our inode cache.  Isn't it pretty?
   */
  static struct kmem_cache *exofs_inode_cachep;
  
  /*
   * Allocate an inode in the cache
   */
  static struct inode *exofs_alloc_inode(struct super_block *sb)
  {
  	struct exofs_i_info *oi;
  
  	oi = kmem_cache_alloc(exofs_inode_cachep, GFP_KERNEL);
  	if (!oi)
  		return NULL;
  
  	oi->vfs_inode.i_version = 1;
  	return &oi->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
165
166
167
168
169
170
  static void exofs_i_callback(struct rcu_head *head)
  {
  	struct inode *inode = container_of(head, struct inode, i_rcu);
  	INIT_LIST_HEAD(&inode->i_dentry);
  	kmem_cache_free(exofs_inode_cachep, exofs_i(inode));
  }
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
171
172
173
174
175
  /*
   * Remove an inode from the cache
   */
  static void exofs_destroy_inode(struct inode *inode)
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
176
  	call_rcu(&inode->i_rcu, exofs_i_callback);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  }
  
  /*
   * Initialize the inode
   */
  static void exofs_init_once(void *foo)
  {
  	struct exofs_i_info *oi = foo;
  
  	inode_init_once(&oi->vfs_inode);
  }
  
  /*
   * Create and initialize the inode cache
   */
  static int init_inodecache(void)
  {
  	exofs_inode_cachep = kmem_cache_create("exofs_inode_cache",
  				sizeof(struct exofs_i_info), 0,
  				SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
  				exofs_init_once);
  	if (exofs_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  /*
   * Destroy the inode cache
   */
  static void destroy_inodecache(void)
  {
  	kmem_cache_destroy(exofs_inode_cachep);
  }
  
  /******************************************************************************
   * SUPERBLOCK FUNCTIONS
   *****************************************************************************/
  static const struct super_operations exofs_sops;
8cf74b393   Boaz Harrosh   exofs: export_ope...
215
  static const struct export_operations exofs_export_ops;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
216

1cea312ad   Boaz Harrosh   exofs: Write sbi-...
217
218
219
220
221
222
223
224
225
226
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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
310
311
312
313
314
315
316
  static const struct osd_attr g_attr_sb_stats = ATTR_DEF(
  	EXOFS_APAGE_SB_DATA,
  	EXOFS_ATTR_SB_STATS,
  	sizeof(struct exofs_sb_stats));
  
  static int __sbi_read_stats(struct exofs_sb_info *sbi)
  {
  	struct osd_attr attrs[] = {
  		[0] = g_attr_sb_stats,
  	};
  	struct exofs_io_state *ios;
  	int ret;
  
  	ret = exofs_get_io_state(&sbi->layout, &ios);
  	if (unlikely(ret)) {
  		EXOFS_ERR("%s: exofs_get_io_state failed.
  ", __func__);
  		return ret;
  	}
  
  	ios->cred = sbi->s_cred;
  
  	ios->in_attr = attrs;
  	ios->in_attr_len = ARRAY_SIZE(attrs);
  
  	ret = exofs_sbi_read(ios);
  	if (unlikely(ret)) {
  		EXOFS_ERR("Error reading super_block stats => %d
  ", ret);
  		goto out;
  	}
  
  	ret = extract_attr_from_ios(ios, &attrs[0]);
  	if (ret) {
  		EXOFS_ERR("%s: extract_attr of sb_stats failed
  ", __func__);
  		goto out;
  	}
  	if (attrs[0].len) {
  		struct exofs_sb_stats *ess;
  
  		if (unlikely(attrs[0].len != sizeof(*ess))) {
  			EXOFS_ERR("%s: Wrong version of exofs_sb_stats "
  				  "size(%d) != expected(%zd)
  ",
  				  __func__, attrs[0].len, sizeof(*ess));
  			goto out;
  		}
  
  		ess = attrs[0].val_ptr;
  		sbi->s_nextid = le64_to_cpu(ess->s_nextid);
  		sbi->s_numfiles = le32_to_cpu(ess->s_numfiles);
  	}
  
  out:
  	exofs_put_io_state(ios);
  	return ret;
  }
  
  static void stats_done(struct exofs_io_state *ios, void *p)
  {
  	exofs_put_io_state(ios);
  	/* Good thanks nothing to do anymore */
  }
  
  /* Asynchronously write the stats attribute */
  int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
  {
  	struct osd_attr attrs[] = {
  		[0] = g_attr_sb_stats,
  	};
  	struct exofs_io_state *ios;
  	int ret;
  
  	ret = exofs_get_io_state(&sbi->layout, &ios);
  	if (unlikely(ret)) {
  		EXOFS_ERR("%s: exofs_get_io_state failed.
  ", __func__);
  		return ret;
  	}
  
  	sbi->s_ess.s_nextid   = cpu_to_le64(sbi->s_nextid);
  	sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles);
  	attrs[0].val_ptr = &sbi->s_ess;
  
  	ios->cred = sbi->s_cred;
  	ios->done = stats_done;
  	ios->private = sbi;
  	ios->out_attr = attrs;
  	ios->out_attr_len = ARRAY_SIZE(attrs);
  
  	ret = exofs_sbi_write(ios);
  	if (unlikely(ret)) {
  		EXOFS_ERR("%s: exofs_sbi_write failed.
  ", __func__);
  		exofs_put_io_state(ios);
  	}
  
  	return ret;
  }
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
317
318
319
  /*
   * Write the superblock to the OSD
   */
baaf94cdc   Boaz Harrosh   exofs: Avoid usin...
320
  int exofs_sync_fs(struct super_block *sb, int wait)
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
321
322
323
  {
  	struct exofs_sb_info *sbi;
  	struct exofs_fscb *fscb;
06886a5a3   Boaz Harrosh   exofs: Move all o...
324
  	struct exofs_io_state *ios;
80e09fb94   Christoph Hellwig   exofs: add ->sync_fs
325
  	int ret = -ENOMEM;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
326

1cea312ad   Boaz Harrosh   exofs: Write sbi-...
327
328
329
  	fscb = kmalloc(sizeof(*fscb), GFP_KERNEL);
  	if (unlikely(!fscb))
  		return -ENOMEM;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
330
  	sbi = sb->s_fs_info;
06886a5a3   Boaz Harrosh   exofs: Move all o...
331

1cea312ad   Boaz Harrosh   exofs: Write sbi-...
332
333
334
335
336
337
338
  	/* NOTE: We no longer dirty the super_block anywhere in exofs. The
  	 * reason we write the fscb here on unmount is so we can stay backwards
  	 * compatible with fscb->s_version == 1. (What we are not compatible
  	 * with is if a new version FS crashed and then we try to mount an old
  	 * version). Otherwise the exofs_fscb is read-only from mkfs time. All
  	 * the writeable info is set in exofs_sbi_write_stats() above.
  	 */
45d3abcb1   Boaz Harrosh   exofs: Move layou...
339
  	ret = exofs_get_io_state(&sbi->layout, &ios);
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
340
  	if (unlikely(ret))
06886a5a3   Boaz Harrosh   exofs: Move all o...
341
  		goto out;
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
342
  	lock_super(sb);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
343
  	ios->length = offsetof(struct exofs_fscb, s_dev_table_oid);
06886a5a3   Boaz Harrosh   exofs: Move all o...
344
  	memset(fscb, 0, ios->length);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
345
346
347
348
  	fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
  	fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles);
  	fscb->s_magic = cpu_to_le16(sb->s_magic);
  	fscb->s_newfs = 0;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
349
  	fscb->s_version = EXOFS_FSCB_VER;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
350

06886a5a3   Boaz Harrosh   exofs: Move all o...
351
352
353
354
  	ios->obj.id = EXOFS_SUPER_ID;
  	ios->offset = 0;
  	ios->kern_buff = fscb;
  	ios->cred = sbi->s_cred;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
355

06886a5a3   Boaz Harrosh   exofs: Move all o...
356
  	ret = exofs_sbi_write(ios);
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
357
  	if (unlikely(ret))
06886a5a3   Boaz Harrosh   exofs: Move all o...
358
359
  		EXOFS_ERR("%s: exofs_sbi_write failed.
  ", __func__);
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
360
361
  	else
  		sb->s_dirt = 0;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
362

1cea312ad   Boaz Harrosh   exofs: Write sbi-...
363
  	unlock_super(sb);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
364
  out:
06886a5a3   Boaz Harrosh   exofs: Move all o...
365
366
367
  	EXOFS_DBGMSG("s_nextid=0x%llx ret=%d
  ", _LLU(sbi->s_nextid), ret);
  	exofs_put_io_state(ios);
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
368
  	kfree(fscb);
80e09fb94   Christoph Hellwig   exofs: add ->sync_fs
369
370
371
372
373
374
375
376
377
  	return ret;
  }
  
  static void exofs_write_super(struct super_block *sb)
  {
  	if (!(sb->s_flags & MS_RDONLY))
  		exofs_sync_fs(sb, 1);
  	else
  		sb->s_dirt = 0;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
378
  }
19fe294f2   Boaz Harrosh   exofs: Prints on ...
379
380
381
382
383
384
385
386
387
  static void _exofs_print_device(const char *msg, const char *dev_path,
  				struct osd_dev *od, u64 pid)
  {
  	const struct osd_dev_info *odi = osduld_device_info(od);
  
  	printk(KERN_NOTICE "exofs: %s %s osd_name-%s pid-0x%llx
  ",
  		msg, dev_path ?: "", odi->osdname, _LLU(pid));
  }
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
388
389
  void exofs_free_sbi(struct exofs_sb_info *sbi)
  {
45d3abcb1   Boaz Harrosh   exofs: Move layou...
390
391
392
  	while (sbi->layout.s_numdevs) {
  		int i = --sbi->layout.s_numdevs;
  		struct osd_dev *od = sbi->layout.s_ods[i];
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
393
394
  
  		if (od) {
45d3abcb1   Boaz Harrosh   exofs: Move layou...
395
  			sbi->layout.s_ods[i] = NULL;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
396
397
398
399
400
  			osduld_put_device(od);
  		}
  	}
  	kfree(sbi);
  }
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
401
402
403
404
405
406
407
408
409
410
411
412
413
  /*
   * This function is called when the vfs is freeing the superblock.  We just
   * need to free our own part.
   */
  static void exofs_put_super(struct super_block *sb)
  {
  	int num_pend;
  	struct exofs_sb_info *sbi = sb->s_fs_info;
  
  	/* make sure there are no pending commands */
  	for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0;
  	     num_pend = atomic_read(&sbi->s_curr_pending)) {
  		wait_queue_head_t wq;
a49fb4c3d   Boaz Harrosh   exofs: deprecate ...
414
415
416
417
418
  
  		printk(KERN_NOTICE "%s: !!Pending operations in flight. "
  		       "This is a BUG. please report to osd-dev@open-osd.org
  ",
  		       __func__);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
419
420
421
422
423
  		init_waitqueue_head(&wq);
  		wait_event_timeout(wq,
  				  (atomic_read(&sbi->s_curr_pending) == 0),
  				  msecs_to_jiffies(100));
  	}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
424
425
  	_exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0],
  			    sbi->layout.s_pid);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
426

b3d0ab7e6   Jens Axboe   exofs: add bdi ba...
427
  	bdi_destroy(&sbi->bdi);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
428
  	exofs_free_sbi(sbi);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
429
430
  	sb->s_fs_info = NULL;
  }
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
431
432
433
  static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
  				    struct exofs_device_table *dt)
  {
5d952b839   Boaz Harrosh   exofs: RAID0 support
434
  	u64 stripe_length;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
435
436
437
438
439
440
441
442
443
444
445
446
  	sbi->data_map.odm_num_comps   =
  				le32_to_cpu(dt->dt_data_map.cb_num_comps);
  	sbi->data_map.odm_stripe_unit =
  				le64_to_cpu(dt->dt_data_map.cb_stripe_unit);
  	sbi->data_map.odm_group_width =
  				le32_to_cpu(dt->dt_data_map.cb_group_width);
  	sbi->data_map.odm_group_depth =
  				le32_to_cpu(dt->dt_data_map.cb_group_depth);
  	sbi->data_map.odm_mirror_cnt  =
  				le32_to_cpu(dt->dt_data_map.cb_mirror_cnt);
  	sbi->data_map.odm_raid_algorithm  =
  				le32_to_cpu(dt->dt_data_map.cb_raid_algorithm);
50a76fd3c   Boaz Harrosh   exofs: groups sup...
447
  /* FIXME: Only raid0 for now. if not so, do not mount */
5d952b839   Boaz Harrosh   exofs: RAID0 support
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  	if (sbi->data_map.odm_num_comps != numdevs) {
  		EXOFS_ERR("odm_num_comps(%u) != numdevs(%u)
  ",
  			  sbi->data_map.odm_num_comps, numdevs);
  		return -EINVAL;
  	}
  	if (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) {
  		EXOFS_ERR("Only RAID_0 for now
  ");
  		return -EINVAL;
  	}
  	if (0 != (numdevs % (sbi->data_map.odm_mirror_cnt + 1))) {
  		EXOFS_ERR("Data Map wrong, numdevs=%d mirrors=%d
  ",
  			  numdevs, sbi->data_map.odm_mirror_cnt);
  		return -EINVAL;
  	}
5d952b839   Boaz Harrosh   exofs: RAID0 support
465
466
467
468
469
470
471
472
473
474
  	if (0 != (sbi->data_map.odm_stripe_unit & ~PAGE_MASK)) {
  		EXOFS_ERR("Stripe Unit(0x%llx)"
  			  " must be Multples of PAGE_SIZE(0x%lx)
  ",
  			  _LLU(sbi->data_map.odm_stripe_unit), PAGE_SIZE);
  		return -EINVAL;
  	}
  
  	sbi->layout.stripe_unit = sbi->data_map.odm_stripe_unit;
  	sbi->layout.mirrors_p1 = sbi->data_map.odm_mirror_cnt + 1;
50a76fd3c   Boaz Harrosh   exofs: groups sup...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  
  	if (sbi->data_map.odm_group_width) {
  		sbi->layout.group_width = sbi->data_map.odm_group_width;
  		sbi->layout.group_depth = sbi->data_map.odm_group_depth;
  		if (!sbi->layout.group_depth) {
  			EXOFS_ERR("group_depth == 0 && group_width != 0
  ");
  			return -EINVAL;
  		}
  		sbi->layout.group_count = sbi->data_map.odm_num_comps /
  						sbi->layout.mirrors_p1 /
  						sbi->data_map.odm_group_width;
  	} else {
  		if (sbi->data_map.odm_group_depth) {
  			printk(KERN_NOTICE "Warning: group_depth ignored "
  				"group_width == 0 && group_depth == %d
  ",
  				sbi->data_map.odm_group_depth);
  			sbi->data_map.odm_group_depth = 0;
  		}
  		sbi->layout.group_width = sbi->data_map.odm_num_comps /
5d952b839   Boaz Harrosh   exofs: RAID0 support
496
  							sbi->layout.mirrors_p1;
50a76fd3c   Boaz Harrosh   exofs: groups sup...
497
498
499
500
501
502
503
504
505
506
507
  		sbi->layout.group_depth = -1;
  		sbi->layout.group_count = 1;
  	}
  
  	stripe_length = (u64)sbi->layout.group_width * sbi->layout.stripe_unit;
  	if (stripe_length >= (1ULL << 32)) {
  		EXOFS_ERR("Total Stripe length(0x%llx)"
  			  " >= 32bit is not supported
  ", _LLU(stripe_length));
  		return -EINVAL;
  	}
5d952b839   Boaz Harrosh   exofs: RAID0 support
508
509
  
  	return 0;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
510
  }
66cd6cad4   bharrosh@panasas.com   exofs: Override r...
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
  static unsigned __ra_pages(struct exofs_layout *layout)
  {
  	const unsigned _MIN_RA = 32; /* min 128K read-ahead */
  	unsigned ra_pages = layout->group_width * layout->stripe_unit /
  				PAGE_SIZE;
  	unsigned max_io_pages = exofs_max_io_pages(layout, ~0);
  
  	ra_pages *= 2; /* two stripes */
  	if (ra_pages < _MIN_RA)
  		ra_pages = roundup(_MIN_RA, ra_pages / 2);
  
  	if (ra_pages > max_io_pages)
  		ra_pages = max_io_pages;
  
  	return ra_pages;
  }
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
  /* @odi is valid only as long as @fscb_dev is valid */
  static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
  			     struct osd_dev_info *odi)
  {
  	odi->systemid_len = le32_to_cpu(dt_dev->systemid_len);
  	memcpy(odi->systemid, dt_dev->systemid, odi->systemid_len);
  
  	odi->osdname_len = le32_to_cpu(dt_dev->osdname_len);
  	odi->osdname = dt_dev->osdname;
  
  	/* FIXME support long names. Will need a _put function */
  	if (dt_dev->long_name_offset)
  		return -EINVAL;
  
  	/* Make sure osdname is printable!
  	 * mkexofs should give us space for a null-terminator else the
  	 * device-table is invalid.
  	 */
  	if (unlikely(odi->osdname_len >= sizeof(dt_dev->osdname)))
  		odi->osdname_len = sizeof(dt_dev->osdname) - 1;
  	dt_dev->osdname[odi->osdname_len] = 0;
  
  	/* If it's all zeros something is bad we read past end-of-obj */
  	return !(odi->systemid_len || odi->osdname_len);
  }
  
  static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
  				       unsigned table_count)
  {
  	struct exofs_sb_info *sbi = *psbi;
  	struct osd_dev *fscb_od;
45d3abcb1   Boaz Harrosh   exofs: Move layou...
558
  	struct osd_obj_id obj = {.partition = sbi->layout.s_pid,
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
  				 .id = EXOFS_DEVTABLE_ID};
  	struct exofs_device_table *dt;
  	unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) +
  					     sizeof(*dt);
  	unsigned numdevs, i;
  	int ret;
  
  	dt = kmalloc(table_bytes, GFP_KERNEL);
  	if (unlikely(!dt)) {
  		EXOFS_ERR("ERROR: allocating %x bytes for device table
  ",
  			  table_bytes);
  		return -ENOMEM;
  	}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
573
574
575
  	fscb_od = sbi->layout.s_ods[0];
  	sbi->layout.s_ods[0] = NULL;
  	sbi->layout.s_numdevs = 0;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  	ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes);
  	if (unlikely(ret)) {
  		EXOFS_ERR("ERROR: reading device table
  ");
  		goto out;
  	}
  
  	numdevs = le64_to_cpu(dt->dt_num_devices);
  	if (unlikely(!numdevs)) {
  		ret = -EINVAL;
  		goto out;
  	}
  	WARN_ON(table_count != numdevs);
  
  	ret = _read_and_match_data_map(sbi, numdevs, dt);
  	if (unlikely(ret))
  		goto out;
  
  	if (likely(numdevs > 1)) {
45d3abcb1   Boaz Harrosh   exofs: Move layou...
595
  		unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
596
597
598
599
600
601
  
  		sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL);
  		if (unlikely(!sbi)) {
  			ret = -ENOMEM;
  			goto out;
  		}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
602
603
  		memset(&sbi->layout.s_ods[1], 0,
  		       size - sizeof(sbi->layout.s_ods[0]));
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  		*psbi = sbi;
  	}
  
  	for (i = 0; i < numdevs; i++) {
  		struct exofs_fscb fscb;
  		struct osd_dev_info odi;
  		struct osd_dev *od;
  
  		if (exofs_devs_2_odi(&dt->dt_dev_table[i], &odi)) {
  			EXOFS_ERR("ERROR: Read all-zeros device entry
  ");
  			ret = -EINVAL;
  			goto out;
  		}
  
  		printk(KERN_NOTICE "Add device[%d]: osd_name-%s
  ",
  		       i, odi.osdname);
  
  		/* On all devices the device table is identical. The user can
  		 * specify any one of the participating devices on the command
  		 * line. We always keep them in device-table order.
  		 */
  		if (fscb_od && osduld_device_same(fscb_od, &odi)) {
45d3abcb1   Boaz Harrosh   exofs: Move layou...
628
629
  			sbi->layout.s_ods[i] = fscb_od;
  			++sbi->layout.s_numdevs;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
630
631
632
633
634
  			fscb_od = NULL;
  			continue;
  		}
  
  		od = osduld_info_lookup(&odi);
2c722c9a4   Tobias Klauser   exofs: Remove red...
635
  		if (IS_ERR(od)) {
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
636
637
638
639
640
641
  			ret = PTR_ERR(od);
  			EXOFS_ERR("ERROR: device requested is not found "
  				  "osd_name-%s =>%d
  ", odi.osdname, ret);
  			goto out;
  		}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
642
643
  		sbi->layout.s_ods[i] = od;
  		++sbi->layout.s_numdevs;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  
  		/* Read the fscb of the other devices to make sure the FS
  		 * partition is there.
  		 */
  		ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb,
  				      sizeof(fscb));
  		if (unlikely(ret)) {
  			EXOFS_ERR("ERROR: Malformed participating device "
  				  "error reading fscb osd_name-%s
  ",
  				  odi.osdname);
  			goto out;
  		}
  
  		/* TODO: verify other information is correct and FS-uuid
  		 *	 matches. Benny what did you say about device table
  		 *	 generation and old devices?
  		 */
  	}
  
  out:
  	kfree(dt);
  	if (unlikely(!ret && fscb_od)) {
  		EXOFS_ERR(
  		      "ERROR: Bad device-table container device not present
  ");
  		osduld_put_device(fscb_od);
  		ret = -EINVAL;
  	}
  
  	return ret;
  }
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
676
677
678
679
680
681
682
683
  /*
   * Read the superblock from the OSD and fill in the fields
   */
  static int exofs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct inode *root;
  	struct exofs_mountopt *opts = data;
  	struct exofs_sb_info *sbi;	/*extended info                  */
06886a5a3   Boaz Harrosh   exofs: Move all o...
684
  	struct osd_dev *od;		/* Master device                 */
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
685
  	struct exofs_fscb fscb;		/*on-disk superblock info        */
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
686
  	struct osd_obj_id obj;
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
687
  	unsigned table_count;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
688
689
690
691
692
  	int ret;
  
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
  	if (!sbi)
  		return -ENOMEM;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
693

b3d0ab7e6   Jens Axboe   exofs: add bdi ba...
694
695
696
  	ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
  	if (ret)
  		goto free_bdi;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
697
  	/* use mount options to fill superblock */
9ed964843   Boaz Harrosh   exofs: Add option...
698
699
700
701
702
703
704
705
706
  	if (opts->is_osdname) {
  		struct osd_dev_info odi = {.systemid_len = 0};
  
  		odi.osdname_len = strlen(opts->dev_name);
  		odi.osdname = (u8 *)opts->dev_name;
  		od = osduld_info_lookup(&odi);
  	} else {
  		od = osduld_path_lookup(opts->dev_name);
  	}
06886a5a3   Boaz Harrosh   exofs: Move all o...
707
  	if (IS_ERR(od)) {
9ed964843   Boaz Harrosh   exofs: Add option...
708
  		ret = -EINVAL;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
709
710
  		goto free_sbi;
  	}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
711
  	/* Default layout in case we do not have a device-table */
5d952b839   Boaz Harrosh   exofs: RAID0 support
712
713
714
  	sbi->layout.stripe_unit = PAGE_SIZE;
  	sbi->layout.mirrors_p1 = 1;
  	sbi->layout.group_width = 1;
50a76fd3c   Boaz Harrosh   exofs: groups sup...
715
716
  	sbi->layout.group_depth = -1;
  	sbi->layout.group_count = 1;
45d3abcb1   Boaz Harrosh   exofs: Move layou...
717
718
719
  	sbi->layout.s_ods[0] = od;
  	sbi->layout.s_numdevs = 1;
  	sbi->layout.s_pid = opts->pid;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
720
721
722
723
724
725
726
727
728
729
730
  	sbi->s_timeout = opts->timeout;
  
  	/* fill in some other data by hand */
  	memset(sb->s_id, 0, sizeof(sb->s_id));
  	strcpy(sb->s_id, "exofs");
  	sb->s_blocksize = EXOFS_BLKSIZE;
  	sb->s_blocksize_bits = EXOFS_BLKSHIFT;
  	sb->s_maxbytes = MAX_LFS_FILESIZE;
  	atomic_set(&sbi->s_curr_pending, 0);
  	sb->s_bdev = NULL;
  	sb->s_dev = 0;
45d3abcb1   Boaz Harrosh   exofs: Move layou...
731
  	obj.partition = sbi->layout.s_pid;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
732
733
  	obj.id = EXOFS_SUPER_ID;
  	exofs_make_credential(sbi->s_cred, &obj);
06886a5a3   Boaz Harrosh   exofs: Move all o...
734
735
  	ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb));
  	if (unlikely(ret))
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
736
  		goto free_sbi;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
737
738
  
  	sb->s_magic = le16_to_cpu(fscb.s_magic);
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
739
  	/* NOTE: we read below to be backward compatible with old versions */
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
740
741
742
743
744
745
746
747
748
749
750
  	sbi->s_nextid = le64_to_cpu(fscb.s_nextid);
  	sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles);
  
  	/* make sure what we read from the object store is correct */
  	if (sb->s_magic != EXOFS_SUPER_MAGIC) {
  		if (!silent)
  			EXOFS_ERR("ERROR: Bad magic value
  ");
  		ret = -EINVAL;
  		goto free_sbi;
  	}
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
751
  	if (le32_to_cpu(fscb.s_version) > EXOFS_FSCB_VER) {
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
752
753
754
755
756
757
  		EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d
  ",
  			  EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version));
  		ret = -EINVAL;
  		goto free_sbi;
  	}
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
758
759
760
761
  
  	/* start generation numbers from a random point */
  	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
  	spin_lock_init(&sbi->s_next_gen_lock);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
762
763
764
765
766
767
  	table_count = le64_to_cpu(fscb.s_dev_table_count);
  	if (table_count) {
  		ret = exofs_read_lookup_dev_table(&sbi, table_count);
  		if (unlikely(ret))
  			goto free_sbi;
  	}
1cea312ad   Boaz Harrosh   exofs: Write sbi-...
768
  	__sbi_read_stats(sbi);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
769
  	/* set up operation vectors */
66cd6cad4   bharrosh@panasas.com   exofs: Override r...
770
  	sbi->bdi.ra_pages = __ra_pages(&sbi->layout);
b3d0ab7e6   Jens Axboe   exofs: add bdi ba...
771
  	sb->s_bdi = &sbi->bdi;
06886a5a3   Boaz Harrosh   exofs: Move all o...
772
  	sb->s_fs_info = sbi;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
773
  	sb->s_op = &exofs_sops;
8cf74b393   Boaz Harrosh   exofs: export_ope...
774
  	sb->s_export_op = &exofs_export_ops;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
  	root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF);
  	if (IS_ERR(root)) {
  		EXOFS_ERR("ERROR: exofs_iget failed
  ");
  		ret = PTR_ERR(root);
  		goto free_sbi;
  	}
  	sb->s_root = d_alloc_root(root);
  	if (!sb->s_root) {
  		iput(root);
  		EXOFS_ERR("ERROR: get root inode failed
  ");
  		ret = -ENOMEM;
  		goto free_sbi;
  	}
  
  	if (!S_ISDIR(root->i_mode)) {
  		dput(sb->s_root);
  		sb->s_root = NULL;
  		EXOFS_ERR("ERROR: corrupt root inode (mode = %hd)
  ",
  		       root->i_mode);
  		ret = -EINVAL;
  		goto free_sbi;
  	}
45d3abcb1   Boaz Harrosh   exofs: Move layou...
800
801
  	_exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
  			    sbi->layout.s_pid);
9ed964843   Boaz Harrosh   exofs: Add option...
802
803
  	if (opts->is_osdname)
  		kfree(opts->dev_name);
06886a5a3   Boaz Harrosh   exofs: Move all o...
804
  	return 0;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
805
806
  
  free_sbi:
b3d0ab7e6   Jens Axboe   exofs: add bdi ba...
807
808
  	bdi_destroy(&sbi->bdi);
  free_bdi:
06886a5a3   Boaz Harrosh   exofs: Move all o...
809
810
  	EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d
  ",
45d3abcb1   Boaz Harrosh   exofs: Move layou...
811
  		  opts->dev_name, sbi->layout.s_pid, ret);
04dc1e88a   Boaz Harrosh   exofs: Multi-devi...
812
  	exofs_free_sbi(sbi);
9ed964843   Boaz Harrosh   exofs: Add option...
813
814
  	if (opts->is_osdname)
  		kfree(opts->dev_name);
06886a5a3   Boaz Harrosh   exofs: Move all o...
815
  	return ret;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
816
817
818
819
820
  }
  
  /*
   * Set up the superblock (calls exofs_fill_super eventually)
   */
3c26ff6e4   Al Viro   convert get_sb_no...
821
  static struct dentry *exofs_mount(struct file_system_type *type,
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
822
  			  int flags, const char *dev_name,
3c26ff6e4   Al Viro   convert get_sb_no...
823
  			  void *data)
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
824
825
826
827
828
829
  {
  	struct exofs_mountopt opts;
  	int ret;
  
  	ret = parse_options(data, &opts);
  	if (ret)
3c26ff6e4   Al Viro   convert get_sb_no...
830
  		return ERR_PTR(ret);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
831

9ed964843   Boaz Harrosh   exofs: Add option...
832
833
  	if (!opts.dev_name)
  		opts.dev_name = dev_name;
3c26ff6e4   Al Viro   convert get_sb_no...
834
  	return mount_nodev(type, flags, &opts, exofs_fill_super);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
835
836
837
838
839
840
841
842
843
844
  }
  
  /*
   * Return information about the file system state in the buffer.  This is used
   * by the 'df' command, for example.
   */
  static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
  	struct super_block *sb = dentry->d_sb;
  	struct exofs_sb_info *sbi = sb->s_fs_info;
06886a5a3   Boaz Harrosh   exofs: Move all o...
845
  	struct exofs_io_state *ios;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
846
847
848
849
850
851
852
853
  	struct osd_attr attrs[] = {
  		ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS,
  			OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)),
  		ATTR_DEF(OSD_APAGE_PARTITION_INFORMATION,
  			OSD_ATTR_PI_USED_CAPACITY, sizeof(__be64)),
  	};
  	uint64_t capacity = ULLONG_MAX;
  	uint64_t used = ULLONG_MAX;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
854
855
  	uint8_t cred_a[OSD_CAP_LEN];
  	int ret;
45d3abcb1   Boaz Harrosh   exofs: Move layou...
856
  	ret = exofs_get_io_state(&sbi->layout, &ios);
06886a5a3   Boaz Harrosh   exofs: Move all o...
857
858
859
860
  	if (ret) {
  		EXOFS_DBGMSG("exofs_get_io_state failed.
  ");
  		return ret;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
861
  	}
06886a5a3   Boaz Harrosh   exofs: Move all o...
862
863
864
865
866
867
  	exofs_make_credential(cred_a, &ios->obj);
  	ios->cred = sbi->s_cred;
  	ios->in_attr = attrs;
  	ios->in_attr_len = ARRAY_SIZE(attrs);
  
  	ret = exofs_sbi_read(ios);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
868
869
  	if (unlikely(ret))
  		goto out;
06886a5a3   Boaz Harrosh   exofs: Move all o...
870
  	ret = extract_attr_from_ios(ios, &attrs[0]);
cae012d85   Boaz Harrosh   exofs: statfs blo...
871
  	if (likely(!ret)) {
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
872
  		capacity = get_unaligned_be64(attrs[0].val_ptr);
cae012d85   Boaz Harrosh   exofs: statfs blo...
873
874
875
  		if (unlikely(!capacity))
  			capacity = ULLONG_MAX;
  	} else
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
876
877
  		EXOFS_DBGMSG("exofs_statfs: get capacity failed.
  ");
06886a5a3   Boaz Harrosh   exofs: Move all o...
878
  	ret = extract_attr_from_ios(ios, &attrs[1]);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
879
880
881
882
883
884
885
886
887
  	if (likely(!ret))
  		used = get_unaligned_be64(attrs[1].val_ptr);
  	else
  		EXOFS_DBGMSG("exofs_statfs: get used-space failed.
  ");
  
  	/* fill in the stats buffer */
  	buf->f_type = EXOFS_SUPER_MAGIC;
  	buf->f_bsize = EXOFS_BLKSIZE;
cae012d85   Boaz Harrosh   exofs: statfs blo...
888
889
  	buf->f_blocks = capacity >> 9;
  	buf->f_bfree = (capacity - used) >> 9;
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
890
891
892
893
894
895
  	buf->f_bavail = buf->f_bfree;
  	buf->f_files = sbi->s_numfiles;
  	buf->f_ffree = EXOFS_MAX_ID - sbi->s_numfiles;
  	buf->f_namelen = EXOFS_NAME_LEN;
  
  out:
06886a5a3   Boaz Harrosh   exofs: Move all o...
896
  	exofs_put_io_state(ios);
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
897
898
899
900
901
902
903
  	return ret;
  }
  
  static const struct super_operations exofs_sops = {
  	.alloc_inode    = exofs_alloc_inode,
  	.destroy_inode  = exofs_destroy_inode,
  	.write_inode    = exofs_write_inode,
4ec70c9b4   Al Viro   convert exofs to ...
904
  	.evict_inode    = exofs_evict_inode,
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
905
906
  	.put_super      = exofs_put_super,
  	.write_super    = exofs_write_super,
80e09fb94   Christoph Hellwig   exofs: add ->sync_fs
907
  	.sync_fs	= exofs_sync_fs,
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
908
909
910
911
  	.statfs         = exofs_statfs,
  };
  
  /******************************************************************************
8cf74b393   Boaz Harrosh   exofs: export_ope...
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
   * EXPORT OPERATIONS
   *****************************************************************************/
  
  struct dentry *exofs_get_parent(struct dentry *child)
  {
  	unsigned long ino = exofs_parent_ino(child);
  
  	if (!ino)
  		return NULL;
  
  	return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino));
  }
  
  static struct inode *exofs_nfs_get_inode(struct super_block *sb,
  		u64 ino, u32 generation)
  {
  	struct inode *inode;
  
  	inode = exofs_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
  	if (generation && inode->i_generation != generation) {
  		/* we didn't find the right inode.. */
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
  	return inode;
  }
  
  static struct dentry *exofs_fh_to_dentry(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type)
  {
  	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  				    exofs_nfs_get_inode);
  }
  
  static struct dentry *exofs_fh_to_parent(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type)
  {
  	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  				    exofs_nfs_get_inode);
  }
  
  static const struct export_operations exofs_export_ops = {
  	.fh_to_dentry = exofs_fh_to_dentry,
  	.fh_to_parent = exofs_fh_to_parent,
  	.get_parent = exofs_get_parent,
  };
  
  /******************************************************************************
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
962
963
964
965
966
967
968
969
970
   * INSMOD/RMMOD
   *****************************************************************************/
  
  /*
   * struct that describes this file system
   */
  static struct file_system_type exofs_type = {
  	.owner          = THIS_MODULE,
  	.name           = "exofs",
3c26ff6e4   Al Viro   convert get_sb_no...
971
  	.mount          = exofs_mount,
ba9e5e98c   Boaz Harrosh   exofs: super_oper...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
  	.kill_sb        = generic_shutdown_super,
  };
  
  static int __init init_exofs(void)
  {
  	int err;
  
  	err = init_inodecache();
  	if (err)
  		goto out;
  
  	err = register_filesystem(&exofs_type);
  	if (err)
  		goto out_d;
  
  	return 0;
  out_d:
  	destroy_inodecache();
  out:
  	return err;
  }
  
  static void __exit exit_exofs(void)
  {
  	unregister_filesystem(&exofs_type);
  	destroy_inodecache();
  }
  
  MODULE_AUTHOR("Avishay Traeger <avishay@gmail.com>");
  MODULE_DESCRIPTION("exofs");
  MODULE_LICENSE("GPL");
  
  module_init(init_exofs)
  module_exit(exit_exofs)