Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[sfrench/cifs-2.6.git] / fs / 9p / fid.c
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 }