xref: /linux/fs/9p/fid.c (revision 2b8232ce512105e28453f301d1510de8363bccd1)
1 /*
2  * V9FS FID Management
3  *
4  *  Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License version 2
8  *  as published by the Free Software Foundation.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to:
17  *  Free Software Foundation
18  *  51 Franklin Street, Fifth Floor
19  *  Boston, MA  02111-1301  USA
20  *
21  */
22 
23 #include <linux/module.h>
24 #include <linux/errno.h>
25 #include <linux/fs.h>
26 #include <linux/sched.h>
27 #include <linux/idr.h>
28 #include <asm/semaphore.h>
29 #include <net/9p/9p.h>
30 #include <net/9p/client.h>
31 
32 #include "v9fs.h"
33 #include "v9fs_vfs.h"
34 #include "fid.h"
35 
36 /**
37  * v9fs_fid_insert - add a fid to a dentry
38  * @fid: fid to add
39  * @dentry: dentry that it is being added to
40  *
41  */
42 
43 int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
44 {
45 	struct v9fs_dentry *dent;
46 
47 	P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
48 					fid->fid, dentry->d_iname);
49 
50 	dent = dentry->d_fsdata;
51 	if (!dent) {
52 		dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
53 		if (!dent)
54 			return -ENOMEM;
55 
56 		spin_lock_init(&dent->lock);
57 		INIT_LIST_HEAD(&dent->fidlist);
58 		dentry->d_fsdata = dent;
59 	}
60 
61 	spin_lock(&dent->lock);
62 	list_add(&fid->dlist, &dent->fidlist);
63 	spin_unlock(&dent->lock);
64 
65 	return 0;
66 }
67 
68 /**
69  * v9fs_fid_lookup - return a locked fid from a dentry
70  * @dentry: dentry to look for fid in
71  *
72  * find a fid in the dentry, obtain its semaphore and return a reference to it.
73  * code calling lookup is responsible for releasing lock
74  *
75  * TODO: only match fids that have the same uid as current user
76  *
77  */
78 
79 struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
80 {
81 	struct v9fs_dentry *dent;
82 	struct p9_fid *fid;
83 
84 	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
85 	dent = dentry->d_fsdata;
86 	if (dent)
87 		fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);
88 	else
89 		fid = ERR_PTR(-EBADF);
90 
91 	P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
92 	return fid;
93 }
94 
95 /**
96  * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
97  * 	release it
98  * @dentry: dentry to look for fid in
99  *
100  * find a fid in the dentry and then clone to a new private fid
101  *
102  * TODO: only match fids that have the same uid as current user
103  *
104  */
105 
106 struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
107 {
108 	struct p9_fid *ofid, *fid;
109 
110 	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
111 	ofid = v9fs_fid_lookup(dentry);
112 	if (IS_ERR(ofid))
113 		return ofid;
114 
115 	fid = p9_client_walk(ofid, 0, NULL, 1);
116 	return fid;
117 }
118