Blame view

fs/gfs2/export.c 4.9 KB
b3b94faa5   David Teigland   [GFS2] The core o...
1
2
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
3
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
4
5
6
   *
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
e9fc2aa09   Steven Whitehouse   [GFS2] Update cop...
7
   * of the GNU General Public License version 2.
b3b94faa5   David Teigland   [GFS2] The core o...
8
   */
b3b94faa5   David Teigland   [GFS2] The core o...
9
10
11
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
12
  #include <linux/exportfs.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
13
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
14
  #include <linux/crc32.h>
b3b94faa5   David Teigland   [GFS2] The core o...
15
16
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
17
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
18
19
20
21
  #include "dir.h"
  #include "glock.h"
  #include "glops.h"
  #include "inode.h"
b27605837   Steven Whitehouse   GFS2: Rationalise...
22
  #include "super.h"
b3b94faa5   David Teigland   [GFS2] The core o...
23
  #include "rgrp.h"
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
24
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
25

bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
26
  #define GFS2_SMALL_FH_SIZE 4
35dcc52e3   Wendy Cheng   [GFS2] Remove i_m...
27
  #define GFS2_LARGE_FH_SIZE 8
3ebf44902   Steven Whitehouse   [GFS2] Accept old...
28
  #define GFS2_OLD_FH_SIZE 10
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
29

b44b84d76   Al Viro   [GFS2] gfs2 misc ...
30
  static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
b3b94faa5   David Teigland   [GFS2] The core o...
31
32
  			  int connectable)
  {
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
33
  	__be32 *fh = (__force __be32 *)p;
b3b94faa5   David Teigland   [GFS2] The core o...
34
  	struct inode *inode = dentry->d_inode;
c9fd43078   Steven Whitehouse   [GFS2] Tidy up mo...
35
  	struct super_block *sb = inode->i_sb;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
36
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
37

5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
38
39
  	if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
  		*len = GFS2_LARGE_FH_SIZE;
b3b94faa5   David Teigland   [GFS2] The core o...
40
  		return 255;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
41
42
43
44
  	} else if (*len < GFS2_SMALL_FH_SIZE) {
  		*len = GFS2_SMALL_FH_SIZE;
  		return 255;
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
45

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
46
47
48
49
  	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  	fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
  	fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
5acd39673   Steven Whitehouse   [GFS2] Some furth...
50
  	*len = GFS2_SMALL_FH_SIZE;
b3b94faa5   David Teigland   [GFS2] The core o...
51

c9fd43078   Steven Whitehouse   [GFS2] Tidy up mo...
52
  	if (!connectable || inode == sb->s_root->d_inode)
b3b94faa5   David Teigland   [GFS2] The core o...
53
54
55
56
  		return *len;
  
  	spin_lock(&dentry->d_lock);
  	inode = dentry->d_parent->d_inode;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
57
58
  	ip = GFS2_I(inode);
  	igrab(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
59
  	spin_unlock(&dentry->d_lock);
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
60
61
62
63
  	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  	fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
  	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
5acd39673   Steven Whitehouse   [GFS2] Some furth...
64
  	*len = GFS2_LARGE_FH_SIZE;
b3b94faa5   David Teigland   [GFS2] The core o...
65

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
66
  	iput(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
67
68
69
70
71
  
  	return *len;
  }
  
  struct get_name_filldir {
629a21e7e   Al Viro   [GFS2] split and ...
72
  	struct gfs2_inum_host inum;
b3b94faa5   David Teigland   [GFS2] The core o...
73
74
  	char *name;
  };
3699e3a44   Steven Whitehouse   [GFS2] Clean up/s...
75
76
  static int get_name_filldir(void *opaque, const char *name, int length,
  			    loff_t offset, u64 inum, unsigned int type)
b3b94faa5   David Teigland   [GFS2] The core o...
77
  {
3699e3a44   Steven Whitehouse   [GFS2] Clean up/s...
78
  	struct get_name_filldir *gnfd = opaque;
b3b94faa5   David Teigland   [GFS2] The core o...
79

3699e3a44   Steven Whitehouse   [GFS2] Clean up/s...
80
  	if (inum != gnfd->inum.no_addr)
b3b94faa5   David Teigland   [GFS2] The core o...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  		return 0;
  
  	memcpy(gnfd->name, name, length);
  	gnfd->name[length] = 0;
  
  	return 1;
  }
  
  static int gfs2_get_name(struct dentry *parent, char *name,
  			 struct dentry *child)
  {
  	struct inode *dir = parent->d_inode;
  	struct inode *inode = child->d_inode;
  	struct gfs2_inode *dip, *ip;
  	struct get_name_filldir gnfd;
  	struct gfs2_holder gh;
cd915493f   Steven Whitehouse   [GFS2] Change all...
97
  	u64 offset = 0;
b3b94faa5   David Teigland   [GFS2] The core o...
98
  	int error;
dfe4d34b3   Bob Peterson   GFS2: Add readahe...
99
  	struct file_ra_state f_ra = { .start = 0 };
b3b94faa5   David Teigland   [GFS2] The core o...
100
101
102
  
  	if (!dir)
  		return -EINVAL;
b3b94faa5   David Teigland   [GFS2] The core o...
103
104
  	if (!S_ISDIR(dir->i_mode) || !inode)
  		return -EINVAL;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
105
106
  	dip = GFS2_I(dir);
  	ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
107
108
  
  	*name = 0;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
109
110
  	gnfd.inum.no_addr = ip->i_no_addr;
  	gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
b3b94faa5   David Teigland   [GFS2] The core o...
111
112
113
114
115
  	gnfd.name = name;
  
  	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
  	if (error)
  		return error;
dfe4d34b3   Bob Peterson   GFS2: Add readahe...
116
  	error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir, &f_ra);
b3b94faa5   David Teigland   [GFS2] The core o...
117
118
119
120
121
122
123
124
125
126
127
  
  	gfs2_glock_dq_uninit(&gh);
  
  	if (!error && !*name)
  		error = -ENOENT;
  
  	return error;
  }
  
  static struct dentry *gfs2_get_parent(struct dentry *child)
  {
41ced6dcf   Al Viro   switch gfs2, clos...
128
  	return d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
b3b94faa5   David Teigland   [GFS2] The core o...
129
  }
34c0d1542   Christoph Hellwig   gfs2: new export ops
130
  static struct dentry *gfs2_get_dentry(struct super_block *sb,
acf7e2444   Steven Whitehouse   GFS2: Be extra ca...
131
  				      struct gfs2_inum_host *inum)
b3b94faa5   David Teigland   [GFS2] The core o...
132
  {
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
133
  	struct gfs2_sbd *sdp = sb->s_fs_info;
b3b94faa5   David Teigland   [GFS2] The core o...
134
  	struct inode *inode;
b3b94faa5   David Teigland   [GFS2] The core o...
135

4667a0ec3   Steven Whitehouse   GFS2: Make writeb...
136
  	inode = gfs2_ilookup(sb, inum->no_addr, 0);
b3b94faa5   David Teigland   [GFS2] The core o...
137
  	if (inode) {
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
138
  		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
b3b94faa5   David Teigland   [GFS2] The core o...
139
140
141
142
143
  			iput(inode);
  			return ERR_PTR(-ESTALE);
  		}
  		goto out_inode;
  	}
044b9414c   Steven Whitehouse   GFS2: Fix inode d...
144
145
146
147
  	inode = gfs2_lookup_by_inum(sdp, inum->no_addr, &inum->no_formal_ino,
  				    GFS2_BLKST_DINODE);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
148

feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
149
  out_inode:
41ced6dcf   Al Viro   switch gfs2, clos...
150
  	return d_obtain_alias(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
151
  }
34c0d1542   Christoph Hellwig   gfs2: new export ops
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	struct gfs2_inum_host this;
  	__be32 *fh = (__force __be32 *)fid->raw;
  
  	switch (fh_type) {
  	case GFS2_SMALL_FH_SIZE:
  	case GFS2_LARGE_FH_SIZE:
  	case GFS2_OLD_FH_SIZE:
  		this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
  		this.no_formal_ino |= be32_to_cpu(fh[1]);
  		this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
  		this.no_addr |= be32_to_cpu(fh[3]);
  		return gfs2_get_dentry(sb, &this);
  	default:
  		return NULL;
  	}
  }
  
  static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	struct gfs2_inum_host parent;
  	__be32 *fh = (__force __be32 *)fid->raw;
  
  	switch (fh_type) {
  	case GFS2_LARGE_FH_SIZE:
  	case GFS2_OLD_FH_SIZE:
  		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
  		parent.no_formal_ino |= be32_to_cpu(fh[5]);
  		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
  		parent.no_addr |= be32_to_cpu(fh[7]);
  		return gfs2_get_dentry(sb, &parent);
  	default:
  		return NULL;
  	}
  }
396551644   Christoph Hellwig   exportfs: make st...
190
  const struct export_operations gfs2_export_ops = {
b3b94faa5   David Teigland   [GFS2] The core o...
191
  	.encode_fh = gfs2_encode_fh,
34c0d1542   Christoph Hellwig   gfs2: new export ops
192
193
  	.fh_to_dentry = gfs2_fh_to_dentry,
  	.fh_to_parent = gfs2_fh_to_parent,
b3b94faa5   David Teigland   [GFS2] The core o...
194
195
  	.get_name = gfs2_get_name,
  	.get_parent = gfs2_get_parent,
b3b94faa5   David Teigland   [GFS2] The core o...
196
  };