Blame view

fs/ocfs2/export.c 6.25 KB
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /* -*- mode: c; c-basic-offset: 8; -*-
   * vim: noexpandtab sw=8 ts=8 sts=0:
   *
   * export.c
   *
   * Functions to facilitate NFS exporting
   *
   * Copyright (C) 2002, 2005 Oracle.  All rights reserved.
   *
   * This program 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; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This program 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 this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/fs.h>
  #include <linux/types.h>
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
28
29
30
  #include <cluster/masklog.h>
  
  #include "ocfs2.h"
6ca497a83   wengang wang   ocfs2: fix rare s...
31
  #include "alloc.h"
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
32
33
  #include "dir.h"
  #include "dlmglue.h"
379dfe9d0   Mark Fasheh   ocfs2: Hook rest ...
34
  #include "dcache.h"
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
35
36
37
38
  #include "export.h"
  #include "inode.h"
  
  #include "buffer_head_io.h"
6ca497a83   wengang wang   ocfs2: fix rare s...
39
  #include "suballoc.h"
781f200cb   Tao Ma   ocfs2: Remove mas...
40
  #include "ocfs2_trace.h"
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
41
42
43
44
45
46
  
  struct ocfs2_inode_handle
  {
  	u64 ih_blkno;
  	u32 ih_generation;
  };
644f9ab3b   Christoph Hellwig   ocfs2: new export...
47
48
  static struct dentry *ocfs2_get_dentry(struct super_block *sb,
  		struct ocfs2_inode_handle *handle)
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
49
  {
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
50
  	struct inode *inode;
6ca497a83   wengang wang   ocfs2: fix rare s...
51
52
53
  	struct ocfs2_super *osb = OCFS2_SB(sb);
  	u64 blkno = handle->ih_blkno;
  	int status, set;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
54
  	struct dentry *result;
781f200cb   Tao Ma   ocfs2: Remove mas...
55
  	trace_ocfs2_get_dentry_begin(sb, handle, (unsigned long long)blkno);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
56

6ca497a83   wengang wang   ocfs2: fix rare s...
57
  	if (blkno == 0) {
6ca497a83   wengang wang   ocfs2: fix rare s...
58
59
  		result = ERR_PTR(-ESTALE);
  		goto bail;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
60
  	}
6ca497a83   wengang wang   ocfs2: fix rare s...
61
62
63
64
65
66
67
  	inode = ocfs2_ilookup(sb, blkno);
  	/*
  	 * If the inode exists in memory, we only need to check it's
  	 * generation number
  	 */
  	if (inode)
  		goto check_gen;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
68

6ca497a83   wengang wang   ocfs2: fix rare s...
69
70
71
72
73
74
75
76
77
78
79
80
  	/*
  	 * This will synchronize us against ocfs2_delete_inode() on
  	 * all nodes
  	 */
  	status = ocfs2_nfs_sync_lock(osb, 1);
  	if (status < 0) {
  		mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d
  ", status);
  		goto check_err;
  	}
  
  	status = ocfs2_test_inode_bit(osb, blkno, &set);
781f200cb   Tao Ma   ocfs2: Remove mas...
81
  	trace_ocfs2_get_dentry_test_bit(status, set);
6ca497a83   wengang wang   ocfs2: fix rare s...
82
83
84
85
86
87
88
  	if (status < 0) {
  		if (status == -EINVAL) {
  			/*
  			 * The blkno NFS gave us doesn't even show up
  			 * as an inode, we return -ESTALE to be
  			 * nice
  			 */
6ca497a83   wengang wang   ocfs2: fix rare s...
89
  			status = -ESTALE;
781f200cb   Tao Ma   ocfs2: Remove mas...
90
  		} else
6ca497a83   wengang wang   ocfs2: fix rare s...
91
92
  			mlog(ML_ERROR, "test inode bit failed %d
  ", status);
6ca497a83   wengang wang   ocfs2: fix rare s...
93
94
95
96
97
  		goto unlock_nfs_sync;
  	}
  
  	/* If the inode allocator bit is clear, this inode must be stale */
  	if (!set) {
6ca497a83   wengang wang   ocfs2: fix rare s...
98
99
100
101
102
103
104
105
106
107
108
109
  		status = -ESTALE;
  		goto unlock_nfs_sync;
  	}
  
  	inode = ocfs2_iget(osb, blkno, 0, 0);
  
  unlock_nfs_sync:
  	ocfs2_nfs_sync_unlock(osb, 1);
  
  check_err:
  	if (status < 0) {
  		if (status == -ESTALE) {
781f200cb   Tao Ma   ocfs2: Remove mas...
110
111
  			trace_ocfs2_get_dentry_stale((unsigned long long)blkno,
  						     handle->ih_generation);
6ca497a83   wengang wang   ocfs2: fix rare s...
112
113
114
115
116
117
118
119
120
121
  		}
  		result = ERR_PTR(status);
  		goto bail;
  	}
  
  	if (IS_ERR(inode)) {
  		mlog_errno(PTR_ERR(inode));
  		result = (void *)inode;
  		goto bail;
  	}
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
122

6ca497a83   wengang wang   ocfs2: fix rare s...
123
  check_gen:
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
124
125
  	if (handle->ih_generation != inode->i_generation) {
  		iput(inode);
781f200cb   Tao Ma   ocfs2: Remove mas...
126
127
128
  		trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
  						  handle->ih_generation,
  						  inode->i_generation);
6ca497a83   wengang wang   ocfs2: fix rare s...
129
130
  		result = ERR_PTR(-ESTALE);
  		goto bail;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
131
  	}
440037287   Christoph Hellwig   [PATCH] switch al...
132
  	result = d_obtain_alias(inode);
ba87167c0   Al Viro   switch ocfs2, clo...
133
  	if (IS_ERR(result))
6ca497a83   wengang wang   ocfs2: fix rare s...
134
  		mlog_errno(PTR_ERR(result));
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
135

6ca497a83   wengang wang   ocfs2: fix rare s...
136
  bail:
781f200cb   Tao Ma   ocfs2: Remove mas...
137
  	trace_ocfs2_get_dentry_end(result);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
138
139
140
141
142
143
144
145
  	return result;
  }
  
  static struct dentry *ocfs2_get_parent(struct dentry *child)
  {
  	int status;
  	u64 blkno;
  	struct dentry *parent;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
146
  	struct inode *dir = child->d_inode;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
147

781f200cb   Tao Ma   ocfs2: Remove mas...
148
149
  	trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
  			       (unsigned long long)OCFS2_I(dir)->ip_blkno);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
150

e63aecb65   Mark Fasheh   ocfs2: Rename ocf...
151
  	status = ocfs2_inode_lock(dir, NULL, 0);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
152
153
154
155
156
157
  	if (status < 0) {
  		if (status != -ENOENT)
  			mlog_errno(status);
  		parent = ERR_PTR(status);
  		goto bail;
  	}
be94d1170   Mark Fasheh   ocfs2: Provide co...
158
  	status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
159
160
161
162
  	if (status < 0) {
  		parent = ERR_PTR(-ENOENT);
  		goto bail_unlock;
  	}
440037287   Christoph Hellwig   [PATCH] switch al...
163
  	parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0));
379dfe9d0   Mark Fasheh   ocfs2: Hook rest ...
164

ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
165
  bail_unlock:
e63aecb65   Mark Fasheh   ocfs2: Rename ocf...
166
  	ocfs2_inode_unlock(dir, 0);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
167

ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
168
  bail:
781f200cb   Tao Ma   ocfs2: Remove mas...
169
  	trace_ocfs2_get_parent_end(parent);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
170
171
172
  
  	return parent;
  }
1ca1a111b   Mark Fasheh   ocfs2: fix sparse...
173
  static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
174
175
176
177
178
179
180
  			   int connectable)
  {
  	struct inode *inode = dentry->d_inode;
  	int len = *max_len;
  	int type = 1;
  	u64 blkno;
  	u32 generation;
1ca1a111b   Mark Fasheh   ocfs2: fix sparse...
181
  	__le32 *fh = (__force __le32 *) fh_in;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
182

781f200cb   Tao Ma   ocfs2: Remove mas...
183
184
185
  	trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len,
  				    dentry->d_name.name,
  				    fh, len, connectable);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
186

5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
187
188
189
190
191
192
  	if (connectable && (len < 6)) {
  		*max_len = 6;
  		type = 255;
  		goto bail;
  	} else if (len < 3) {
  		*max_len = 3;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
193
194
195
196
197
198
  		type = 255;
  		goto bail;
  	}
  
  	blkno = OCFS2_I(inode)->ip_blkno;
  	generation = inode->i_generation;
781f200cb   Tao Ma   ocfs2: Remove mas...
199
  	trace_ocfs2_encode_fh_self((unsigned long long)blkno, generation);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  
  	len = 3;
  	fh[0] = cpu_to_le32((u32)(blkno >> 32));
  	fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff));
  	fh[2] = cpu_to_le32(generation);
  
  	if (connectable && !S_ISDIR(inode->i_mode)) {
  		struct inode *parent;
  
  		spin_lock(&dentry->d_lock);
  
  		parent = dentry->d_parent->d_inode;
  		blkno = OCFS2_I(parent)->ip_blkno;
  		generation = parent->i_generation;
  
  		fh[3] = cpu_to_le32((u32)(blkno >> 32));
  		fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff));
  		fh[5] = cpu_to_le32(generation);
  
  		spin_unlock(&dentry->d_lock);
  
  		len = 6;
  		type = 2;
781f200cb   Tao Ma   ocfs2: Remove mas...
223
224
  		trace_ocfs2_encode_fh_parent((unsigned long long)blkno,
  					     generation);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
225
  	}
2bd632165   Sunil Mushran   ocfs2/trivial: Re...
226

ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
227
228
229
  	*max_len = len;
  
  bail:
781f200cb   Tao Ma   ocfs2: Remove mas...
230
  	trace_ocfs2_encode_fh_type(type);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
231
232
  	return type;
  }
644f9ab3b   Christoph Hellwig   ocfs2: new export...
233
234
  static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb,
  		struct fid *fid, int fh_len, int fh_type)
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
235
  {
644f9ab3b   Christoph Hellwig   ocfs2: new export...
236
  	struct ocfs2_inode_handle handle;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
237

644f9ab3b   Christoph Hellwig   ocfs2: new export...
238
239
  	if (fh_len < 3 || fh_type > 2)
  		return NULL;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
240

644f9ab3b   Christoph Hellwig   ocfs2: new export...
241
242
243
244
245
  	handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32;
  	handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]);
  	handle.ih_generation = le32_to_cpu(fid->raw[2]);
  	return ocfs2_get_dentry(sb, &handle);
  }
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
246

644f9ab3b   Christoph Hellwig   ocfs2: new export...
247
248
249
250
  static struct dentry *ocfs2_fh_to_parent(struct super_block *sb,
  		struct fid *fid, int fh_len, int fh_type)
  {
  	struct ocfs2_inode_handle parent;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
251

644f9ab3b   Christoph Hellwig   ocfs2: new export...
252
253
  	if (fh_type != 2 || fh_len < 6)
  		return NULL;
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
254

644f9ab3b   Christoph Hellwig   ocfs2: new export...
255
256
257
258
  	parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32;
  	parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]);
  	parent.ih_generation = le32_to_cpu(fid->raw[5]);
  	return ocfs2_get_dentry(sb, &parent);
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
259
  }
396551644   Christoph Hellwig   exportfs: make st...
260
  const struct export_operations ocfs2_export_ops = {
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
261
  	.encode_fh	= ocfs2_encode_fh,
644f9ab3b   Christoph Hellwig   ocfs2: new export...
262
263
  	.fh_to_dentry	= ocfs2_fh_to_dentry,
  	.fh_to_parent	= ocfs2_fh_to_parent,
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
264
  	.get_parent	= ocfs2_get_parent,
ccd979bdb   Mark Fasheh   [PATCH] OCFS2: Th...
265
  };