OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [gfs2/] [ops_export.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3
 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4
 *
5
 * This copyrighted material is made available to anyone wishing to use,
6
 * modify, copy, or redistribute it subject to the terms and conditions
7
 * of the GNU General Public License version 2.
8
 */
9
 
10
#include <linux/slab.h>
11
#include <linux/spinlock.h>
12
#include <linux/completion.h>
13
#include <linux/buffer_head.h>
14
#include <linux/exportfs.h>
15
#include <linux/gfs2_ondisk.h>
16
#include <linux/crc32.h>
17
#include <linux/lm_interface.h>
18
 
19
#include "gfs2.h"
20
#include "incore.h"
21
#include "dir.h"
22
#include "glock.h"
23
#include "glops.h"
24
#include "inode.h"
25
#include "ops_dentry.h"
26
#include "ops_fstype.h"
27
#include "rgrp.h"
28
#include "util.h"
29
 
30
#define GFS2_SMALL_FH_SIZE 4
31
#define GFS2_LARGE_FH_SIZE 8
32
#define GFS2_OLD_FH_SIZE 10
33
 
34
static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
35
                          int connectable)
36
{
37
        __be32 *fh = (__force __be32 *)p;
38
        struct inode *inode = dentry->d_inode;
39
        struct super_block *sb = inode->i_sb;
40
        struct gfs2_inode *ip = GFS2_I(inode);
41
 
42
        if (*len < GFS2_SMALL_FH_SIZE ||
43
            (connectable && *len < GFS2_LARGE_FH_SIZE))
44
                return 255;
45
 
46
        fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
47
        fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
48
        fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
49
        fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
50
        *len = GFS2_SMALL_FH_SIZE;
51
 
52
        if (!connectable || inode == sb->s_root->d_inode)
53
                return *len;
54
 
55
        spin_lock(&dentry->d_lock);
56
        inode = dentry->d_parent->d_inode;
57
        ip = GFS2_I(inode);
58
        igrab(inode);
59
        spin_unlock(&dentry->d_lock);
60
 
61
        fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
62
        fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
63
        fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
64
        fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
65
        *len = GFS2_LARGE_FH_SIZE;
66
 
67
        iput(inode);
68
 
69
        return *len;
70
}
71
 
72
struct get_name_filldir {
73
        struct gfs2_inum_host inum;
74
        char *name;
75
};
76
 
77
static int get_name_filldir(void *opaque, const char *name, int length,
78
                            loff_t offset, u64 inum, unsigned int type)
79
{
80
        struct get_name_filldir *gnfd = opaque;
81
 
82
        if (inum != gnfd->inum.no_addr)
83
                return 0;
84
 
85
        memcpy(gnfd->name, name, length);
86
        gnfd->name[length] = 0;
87
 
88
        return 1;
89
}
90
 
91
static int gfs2_get_name(struct dentry *parent, char *name,
92
                         struct dentry *child)
93
{
94
        struct inode *dir = parent->d_inode;
95
        struct inode *inode = child->d_inode;
96
        struct gfs2_inode *dip, *ip;
97
        struct get_name_filldir gnfd;
98
        struct gfs2_holder gh;
99
        u64 offset = 0;
100
        int error;
101
 
102
        if (!dir)
103
                return -EINVAL;
104
 
105
        if (!S_ISDIR(dir->i_mode) || !inode)
106
                return -EINVAL;
107
 
108
        dip = GFS2_I(dir);
109
        ip = GFS2_I(inode);
110
 
111
        *name = 0;
112
        gnfd.inum.no_addr = ip->i_no_addr;
113
        gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
114
        gnfd.name = name;
115
 
116
        error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
117
        if (error)
118
                return error;
119
 
120
        error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir);
121
 
122
        gfs2_glock_dq_uninit(&gh);
123
 
124
        if (!error && !*name)
125
                error = -ENOENT;
126
 
127
        return error;
128
}
129
 
130
static struct dentry *gfs2_get_parent(struct dentry *child)
131
{
132
        struct qstr dotdot;
133
        struct inode *inode;
134
        struct dentry *dentry;
135
 
136
        gfs2_str2qstr(&dotdot, "..");
137
        inode = gfs2_lookupi(child->d_inode, &dotdot, 1, NULL);
138
 
139
        if (!inode)
140
                return ERR_PTR(-ENOENT);
141
        /*
142
         * In case of an error, @inode carries the error value, and we
143
         * have to return that as a(n invalid) pointer to dentry.
144
         */
145
        if (IS_ERR(inode))
146
                return ERR_PTR(PTR_ERR(inode));
147
 
148
        dentry = d_alloc_anon(inode);
149
        if (!dentry) {
150
                iput(inode);
151
                return ERR_PTR(-ENOMEM);
152
        }
153
 
154
        dentry->d_op = &gfs2_dops;
155
        return dentry;
156
}
157
 
158
static struct dentry *gfs2_get_dentry(struct super_block *sb,
159
                struct gfs2_inum_host *inum)
160
{
161
        struct gfs2_sbd *sdp = sb->s_fs_info;
162
        struct gfs2_holder i_gh, ri_gh, rgd_gh;
163
        struct gfs2_rgrpd *rgd;
164
        struct inode *inode;
165
        struct dentry *dentry;
166
        int error;
167
 
168
        /* System files? */
169
 
170
        inode = gfs2_ilookup(sb, inum->no_addr);
171
        if (inode) {
172
                if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
173
                        iput(inode);
174
                        return ERR_PTR(-ESTALE);
175
                }
176
                goto out_inode;
177
        }
178
 
179
        error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
180
                                  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
181
        if (error)
182
                return ERR_PTR(error);
183
 
184
        error = gfs2_rindex_hold(sdp, &ri_gh);
185
        if (error)
186
                goto fail;
187
 
188
        error = -EINVAL;
189
        rgd = gfs2_blk2rgrpd(sdp, inum->no_addr);
190
        if (!rgd)
191
                goto fail_rindex;
192
 
193
        error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
194
        if (error)
195
                goto fail_rindex;
196
 
197
        error = -ESTALE;
198
        if (gfs2_get_block_type(rgd, inum->no_addr) != GFS2_BLKST_DINODE)
199
                goto fail_rgd;
200
 
201
        gfs2_glock_dq_uninit(&rgd_gh);
202
        gfs2_glock_dq_uninit(&ri_gh);
203
 
204
        inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
205
                                        inum->no_addr,
206
                                        0, 0);
207
        if (!inode)
208
                goto fail;
209
        if (IS_ERR(inode)) {
210
                error = PTR_ERR(inode);
211
                goto fail;
212
        }
213
 
214
        error = gfs2_inode_refresh(GFS2_I(inode));
215
        if (error) {
216
                iput(inode);
217
                goto fail;
218
        }
219
 
220
        /* Pick up the works we bypass in gfs2_inode_lookup */
221
        if (inode->i_state & I_NEW)
222
                gfs2_set_iop(inode);
223
 
224
        if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
225
                iput(inode);
226
                goto fail;
227
        }
228
 
229
        error = -EIO;
230
        if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
231
                iput(inode);
232
                goto fail;
233
        }
234
 
235
        gfs2_glock_dq_uninit(&i_gh);
236
 
237
out_inode:
238
        dentry = d_alloc_anon(inode);
239
        if (!dentry) {
240
                iput(inode);
241
                return ERR_PTR(-ENOMEM);
242
        }
243
 
244
        dentry->d_op = &gfs2_dops;
245
        return dentry;
246
 
247
fail_rgd:
248
        gfs2_glock_dq_uninit(&rgd_gh);
249
 
250
fail_rindex:
251
        gfs2_glock_dq_uninit(&ri_gh);
252
 
253
fail:
254
        gfs2_glock_dq_uninit(&i_gh);
255
        return ERR_PTR(error);
256
}
257
 
258
static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
259
                int fh_len, int fh_type)
260
{
261
        struct gfs2_inum_host this;
262
        __be32 *fh = (__force __be32 *)fid->raw;
263
 
264
        switch (fh_type) {
265
        case GFS2_SMALL_FH_SIZE:
266
        case GFS2_LARGE_FH_SIZE:
267
        case GFS2_OLD_FH_SIZE:
268
                this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
269
                this.no_formal_ino |= be32_to_cpu(fh[1]);
270
                this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
271
                this.no_addr |= be32_to_cpu(fh[3]);
272
                return gfs2_get_dentry(sb, &this);
273
        default:
274
                return NULL;
275
        }
276
}
277
 
278
static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
279
                int fh_len, int fh_type)
280
{
281
        struct gfs2_inum_host parent;
282
        __be32 *fh = (__force __be32 *)fid->raw;
283
 
284
        switch (fh_type) {
285
        case GFS2_LARGE_FH_SIZE:
286
        case GFS2_OLD_FH_SIZE:
287
                parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
288
                parent.no_formal_ino |= be32_to_cpu(fh[5]);
289
                parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
290
                parent.no_addr |= be32_to_cpu(fh[7]);
291
                return gfs2_get_dentry(sb, &parent);
292
        default:
293
                return NULL;
294
        }
295
}
296
 
297
const struct export_operations gfs2_export_ops = {
298
        .encode_fh = gfs2_encode_fh,
299
        .fh_to_dentry = gfs2_fh_to_dentry,
300
        .fh_to_parent = gfs2_fh_to_parent,
301
        .get_name = gfs2_get_name,
302
        .get_parent = gfs2_get_parent,
303
};
304
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.