Blame view

fs/9p/fid.c 7.12 KB
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
1
2
3
  /*
   * V9FS FID Management
   *
ba17674fe   Latchesar Ionkov   9p: attach-per-user
4
   *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
46f6dac25   Eric Van Hensbergen   [PATCH] v9fs: sim...
5
   *  Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
6
7
   *
   *  This program is free software; you can redistribute it and/or modify
42e8c509c   Eric Van Hensbergen   [PATCH] v9fs: upd...
8
9
   *  it under the terms of the GNU General Public License version 2
   *  as published by the Free Software Foundation.
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
10
11
12
13
14
15
16
17
18
19
20
21
22
   *
   *  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:
   *  Free Software Foundation
   *  51 Franklin Street, Fifth Floor
   *  Boston, MA  02111-1301  USA
   *
   */
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
23
24
25
  #include <linux/module.h>
  #include <linux/errno.h>
  #include <linux/fs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
914e26379   Al Viro   [PATCH] severing ...
27
  #include <linux/sched.h>
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
28
  #include <linux/idr.h>
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
29
30
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
31

3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
32
  #include "v9fs.h"
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
33
  #include "v9fs_vfs.h"
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
34
35
36
  #include "fid.h"
  
  /**
ba17674fe   Latchesar Ionkov   9p: attach-per-user
37
38
   * v9fs_fid_add - add a fid to a dentry
   * @dentry: dentry that the fid is being added to
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
39
   * @fid: fid to add
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
40
41
   *
   */
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
42
  int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
43
  {
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
44
  	struct v9fs_dentry *dent;
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
45

5d3851530   Joe Perches   9p: Reduce object...
46
47
48
  	p9_debug(P9_DEBUG_VFS, "fid %d dentry %s
  ",
  		 fid->fid, dentry->d_name.name);
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
49

bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
50
51
52
53
54
  	dent = dentry->d_fsdata;
  	if (!dent) {
  		dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
  		if (!dent)
  			return -ENOMEM;
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
55

bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
56
57
58
  		spin_lock_init(&dent->lock);
  		INIT_LIST_HEAD(&dent->fidlist);
  		dentry->d_fsdata = dent;
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
59
  	}
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
60
61
62
  	spin_lock(&dent->lock);
  	list_add(&fid->dlist, &dent->fidlist);
  	spin_unlock(&dent->lock);
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
63

bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
64
  	return 0;
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
65
66
67
  }
  
  /**
ba17674fe   Latchesar Ionkov   9p: attach-per-user
68
   * v9fs_fid_find - retrieve a fid that belongs to the specified uid
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
69
   * @dentry: dentry to look for fid in
ba17674fe   Latchesar Ionkov   9p: attach-per-user
70
71
   * @uid: return fid that belongs to the specified user
   * @any: if non-zero, return any fid associated with the dentry
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
72
73
   *
   */
ba17674fe   Latchesar Ionkov   9p: attach-per-user
74
  static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any)
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
75
  {
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
76
  	struct v9fs_dentry *dent;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
77
  	struct p9_fid *fid, *ret;
5d3851530   Joe Perches   9p: Reduce object...
78
79
80
  	p9_debug(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d
  ",
  		 dentry->d_name.name, dentry, uid, any);
ba17674fe   Latchesar Ionkov   9p: attach-per-user
81
82
83
84
85
86
87
88
89
90
91
92
  	dent = (struct v9fs_dentry *) dentry->d_fsdata;
  	ret = NULL;
  	if (dent) {
  		spin_lock(&dent->lock);
  		list_for_each_entry(fid, &dent->fidlist, dlist) {
  			if (any || fid->uid == uid) {
  				ret = fid;
  				break;
  			}
  		}
  		spin_unlock(&dent->lock);
  	}
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
93

ba17674fe   Latchesar Ionkov   9p: attach-per-user
94
  	return ret;
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
95
  }
3ed8491c8   Eric Van Hensbergen   [PATCH] v9fs: deb...
96

a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  /*
   * We need to hold v9ses->rename_sem as long as we hold references
   * to returned path array. Array element contain pointers to
   * dentry names.
   */
  static int build_path_from_dentry(struct v9fs_session_info *v9ses,
  				  struct dentry *dentry, char ***names)
  {
  	int n = 0, i;
  	char **wnames;
  	struct dentry *ds;
  
  	for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)
  		n++;
  
  	wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);
  	if (!wnames)
  		goto err_out;
  
  	for (ds = dentry, i = (n-1); i >= 0; i--, ds = ds->d_parent)
  		wnames[i] = (char  *)ds->d_name.name;
  
  	*names = wnames;
  	return n;
  err_out:
  	return -ENOMEM;
  }
7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
124
125
  static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
  					       uid_t uid, int any)
da977b2c7   Eric Van Hensbergen   [PATCH] 9p: fix s...
126
  {
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
127
  	struct dentry *ds;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
128
  	char **wnames, *uname;
7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
129
130
131
  	int i, n, l, clone, access;
  	struct v9fs_session_info *v9ses;
  	struct p9_fid *fid, *old_fid = NULL;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
132

42869c8ad   Aneesh Kumar K.V   fs/9p: Add v9fs_d...
133
  	v9ses = v9fs_dentry2v9ses(dentry);
ba17674fe   Latchesar Ionkov   9p: attach-per-user
134
  	access = v9ses->flags & V9FS_ACCESS_MASK;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
135
136
137
  	fid = v9fs_fid_find(dentry, uid, any);
  	if (fid)
  		return fid;
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
138
139
140
141
142
143
  	/*
  	 * we don't have a matching fid. To do a TWALK we need
  	 * parent fid. We need to prevent rename when we want to
  	 * look at the parent.
  	 */
  	down_read(&v9ses->rename_sem);
ba17674fe   Latchesar Ionkov   9p: attach-per-user
144
145
  	ds = dentry->d_parent;
  	fid = v9fs_fid_find(ds, uid, any);
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
146
147
148
149
150
151
  	if (fid) {
  		/* Found the parent fid do a lookup with that */
  		fid = p9_client_walk(fid, 1, (char **)&dentry->d_name.name, 1);
  		goto fid_out;
  	}
  	up_read(&v9ses->rename_sem);
ba17674fe   Latchesar Ionkov   9p: attach-per-user
152

a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
153
154
155
156
157
158
  	/* start from the root and try to do a lookup */
  	fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any);
  	if (!fid) {
  		/* the user is not attached to the fs yet */
  		if (access == V9FS_ACCESS_SINGLE)
  			return ERR_PTR(-EPERM);
ba17674fe   Latchesar Ionkov   9p: attach-per-user
159

a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
160
161
162
163
  		if (v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses))
  				uname = NULL;
  		else
  			uname = v9ses->uname;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
164

a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
165
166
167
168
  		fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
  				       v9ses->aname);
  		if (IS_ERR(fid))
  			return fid;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
169

a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
170
171
172
173
  		v9fs_fid_add(dentry->d_sb->s_root, fid);
  	}
  	/* If we are root ourself just return that */
  	if (dentry->d_sb->s_root == dentry)
ba17674fe   Latchesar Ionkov   9p: attach-per-user
174
  		return fid;
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
175
176
177
178
179
180
181
182
183
184
185
  	/*
  	 * Do a multipath walk with attached root.
  	 * When walking parent we need to make sure we
  	 * don't have a parallel rename happening
  	 */
  	down_read(&v9ses->rename_sem);
  	n  = build_path_from_dentry(v9ses, dentry, &wnames);
  	if (n < 0) {
  		fid = ERR_PTR(n);
  		goto err_out;
  	}
ba17674fe   Latchesar Ionkov   9p: attach-per-user
186
187
188
189
  	clone = 1;
  	i = 0;
  	while (i < n) {
  		l = min(n - i, P9_MAXWELEM);
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
190
191
192
193
  		/*
  		 * We need to hold rename lock when doing a multipath
  		 * walk to ensure none of the patch component change
  		 */
ba17674fe   Latchesar Ionkov   9p: attach-per-user
194
  		fid = p9_client_walk(fid, l, &wnames[i], clone);
c55703d80   Eric Van Hensbergen   9p: fix bug in at...
195
  		if (IS_ERR(fid)) {
5b0fa207d   Aneesh Kumar K.V   fs/9p: Clunk the ...
196
197
198
199
200
201
202
203
  			if (old_fid) {
  				/*
  				 * If we fail, clunk fid which are mapping
  				 * to path component and not the last component
  				 * of the path.
  				 */
  				p9_client_clunk(old_fid);
  			}
ba17674fe   Latchesar Ionkov   9p: attach-per-user
204
  			kfree(wnames);
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
205
  			goto err_out;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
206
  		}
5b0fa207d   Aneesh Kumar K.V   fs/9p: Clunk the ...
207
  		old_fid = fid;
ba17674fe   Latchesar Ionkov   9p: attach-per-user
208
209
210
  		i += l;
  		clone = 0;
  	}
ba17674fe   Latchesar Ionkov   9p: attach-per-user
211
  	kfree(wnames);
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
212
  fid_out:
8f587df47   Dan Carpenter   9p: potential ERR...
213
214
  	if (!IS_ERR(fid))
  		v9fs_fid_add(dentry, fid);
a534c8d15   Aneesh Kumar K.V   fs/9p: Prevent pa...
215
216
  err_out:
  	up_read(&v9ses->rename_sem);
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
217
  	return fid;
da977b2c7   Eric Van Hensbergen   [PATCH] 9p: fix s...
218
  }
ba17674fe   Latchesar Ionkov   9p: attach-per-user
219

7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  /**
   * v9fs_fid_lookup - lookup for a fid, try to walk if not found
   * @dentry: dentry to look for fid in
   *
   * Look for a fid in the specified dentry for the current user.
   * If no fid is found, try to create one walking from a fid from the parent
   * dentry (if it has one), or the root dentry. If the user haven't accessed
   * the fs yet, attach now and walk from the root.
   */
  
  struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
  {
  	uid_t uid;
  	int  any, access;
  	struct v9fs_session_info *v9ses;
42869c8ad   Aneesh Kumar K.V   fs/9p: Add v9fs_d...
235
  	v9ses = v9fs_dentry2v9ses(dentry);
7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  	access = v9ses->flags & V9FS_ACCESS_MASK;
  	switch (access) {
  	case V9FS_ACCESS_SINGLE:
  	case V9FS_ACCESS_USER:
  	case V9FS_ACCESS_CLIENT:
  		uid = current_fsuid();
  		any = 0;
  		break;
  
  	case V9FS_ACCESS_ANY:
  		uid = v9ses->uid;
  		any = 1;
  		break;
  
  	default:
  		uid = ~0;
  		any = 0;
  		break;
  	}
  	return v9fs_fid_lookup_with_uid(dentry, uid, any);
  }
ba17674fe   Latchesar Ionkov   9p: attach-per-user
257
258
259
260
261
262
263
264
265
266
267
  struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
  {
  	struct p9_fid *fid, *ret;
  
  	fid = v9fs_fid_lookup(dentry);
  	if (IS_ERR(fid))
  		return fid;
  
  	ret = p9_client_walk(fid, 0, NULL, 1);
  	return ret;
  }
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
268

7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
269
270
271
272
273
274
275
276
277
278
279
  static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid)
  {
  	struct p9_fid *fid, *ret;
  
  	fid = v9fs_fid_lookup_with_uid(dentry, uid, 0);
  	if (IS_ERR(fid))
  		return fid;
  
  	ret = p9_client_walk(fid, 0, NULL, 1);
  	return ret;
  }
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
280
281
282
  
  struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
  {
df5d8c80f   Aneesh Kumar K.V   9p: revert tsyncf...
283
  	int err;
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
284
  	struct p9_fid *fid;
7c9e592e1   Aneesh Kumar K.V   fs/9p: Make the w...
285
  	fid = v9fs_fid_clone_with_uid(dentry, 0);
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
286
287
288
289
290
291
292
  	if (IS_ERR(fid))
  		goto error_out;
  	/*
  	 * writeback fid will only be used to write back the
  	 * dirty pages. We always request for the open fid in read-write
  	 * mode so that a partial page write which result in page
  	 * read can work.
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
293
  	 */
df5d8c80f   Aneesh Kumar K.V   9p: revert tsyncf...
294
  	err = p9_client_open(fid, O_RDWR);
3cf387d78   Aneesh Kumar K.V   fs/9p: Add fid to...
295
296
297
298
299
300
301
302
  	if (err < 0) {
  		p9_client_clunk(fid);
  		fid = ERR_PTR(err);
  		goto error_out;
  	}
  error_out:
  	return fid;
  }