This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / xfs / linux-2.6 / xfs_export.c
1 /*
2  * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include "xfs.h"
34
35
36 STATIC struct dentry *
37 linvfs_decode_fh(
38         struct super_block      *sb,
39         __u32                   *fh,
40         int                     fh_len,
41         int                     fileid_type,
42         int (*acceptable)(
43                 void            *context,
44                 struct dentry   *de),
45         void                    *context)
46 {
47         __u32 parent[2];
48         parent[0] = parent[1] = 0;
49         
50         if (fh_len < 2 || fileid_type > 2)
51                 return NULL;
52         
53         if (fileid_type == 2 && fh_len > 2) {
54                 if (fh_len == 3) {
55                         printk(KERN_WARNING
56                                "XFS: detected filehandle without "
57                                "parent inode generation information.");
58                         return ERR_PTR(-ESTALE);
59                 }
60                         
61                 parent[0] = fh[2];
62                 parent[1] = fh[3];
63         }
64         
65         return find_exported_dentry(sb, fh, parent, acceptable, context);
66
67 }
68
69 STATIC struct dentry *
70 linvfs_get_dentry(
71         struct super_block      *sb,
72         void                    *data)
73 {
74         vnode_t                 *vp;
75         struct inode            *inode;
76         struct dentry           *result;
77         xfs_fid2_t              xfid;
78         vfs_t                   *vfsp = LINVFS_GET_VFS(sb);
79         int                     error;
80
81         xfid.fid_len = sizeof(xfs_fid2_t) - sizeof(xfid.fid_len);
82         xfid.fid_pad = 0;
83         xfid.fid_gen = ((__u32 *)data)[1];
84         xfid.fid_ino = ((__u32 *)data)[0];
85
86         VFS_VGET(vfsp, &vp, (fid_t *)&xfid, error);
87         if (error || vp == NULL)
88                 return ERR_PTR(-ESTALE) ;
89
90         inode = LINVFS_GET_IP(vp);
91         result = d_alloc_anon(inode);
92         if (!result) {
93                 iput(inode);
94                 return ERR_PTR(-ENOMEM);
95         }
96         return result;
97 }
98
99 STATIC struct dentry *
100 linvfs_get_parent(
101         struct dentry           *child)
102 {
103         int                     error;
104         vnode_t                 *vp, *cvp;
105         struct dentry           *parent;
106         struct dentry           dotdot;
107
108         dotdot.d_name.name = "..";
109         dotdot.d_name.len = 2;
110         dotdot.d_inode = NULL;
111
112         cvp = NULL;
113         vp = LINVFS_GET_VP(child->d_inode);
114         VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error);
115         if (unlikely(error))
116                 return ERR_PTR(-error);
117
118         parent = d_alloc_anon(LINVFS_GET_IP(cvp));
119         if (unlikely(!parent)) {
120                 VN_RELE(cvp);
121                 return ERR_PTR(-ENOMEM);
122         }
123         return parent;
124 }
125
126 struct export_operations linvfs_export_ops = {
127         .decode_fh              = linvfs_decode_fh,
128         .get_parent             = linvfs_get_parent,
129         .get_dentry             = linvfs_get_dentry,
130 };