xref: /openbmc/linux/fs/gfs2/export.c (revision 7dd65feb)
1  /*
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  
18  #include "gfs2.h"
19  #include "incore.h"
20  #include "dir.h"
21  #include "glock.h"
22  #include "glops.h"
23  #include "inode.h"
24  #include "super.h"
25  #include "rgrp.h"
26  #include "util.h"
27  
28  #define GFS2_SMALL_FH_SIZE 4
29  #define GFS2_LARGE_FH_SIZE 8
30  #define GFS2_OLD_FH_SIZE 10
31  
32  static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
33  			  int connectable)
34  {
35  	__be32 *fh = (__force __be32 *)p;
36  	struct inode *inode = dentry->d_inode;
37  	struct super_block *sb = inode->i_sb;
38  	struct gfs2_inode *ip = GFS2_I(inode);
39  
40  	if (*len < GFS2_SMALL_FH_SIZE ||
41  	    (connectable && *len < GFS2_LARGE_FH_SIZE))
42  		return 255;
43  
44  	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
45  	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
46  	fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
47  	fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
48  	*len = GFS2_SMALL_FH_SIZE;
49  
50  	if (!connectable || inode == sb->s_root->d_inode)
51  		return *len;
52  
53  	spin_lock(&dentry->d_lock);
54  	inode = dentry->d_parent->d_inode;
55  	ip = GFS2_I(inode);
56  	igrab(inode);
57  	spin_unlock(&dentry->d_lock);
58  
59  	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
60  	fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
61  	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
62  	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
63  	*len = GFS2_LARGE_FH_SIZE;
64  
65  	iput(inode);
66  
67  	return *len;
68  }
69  
70  struct get_name_filldir {
71  	struct gfs2_inum_host inum;
72  	char *name;
73  };
74  
75  static int get_name_filldir(void *opaque, const char *name, int length,
76  			    loff_t offset, u64 inum, unsigned int type)
77  {
78  	struct get_name_filldir *gnfd = opaque;
79  
80  	if (inum != gnfd->inum.no_addr)
81  		return 0;
82  
83  	memcpy(gnfd->name, name, length);
84  	gnfd->name[length] = 0;
85  
86  	return 1;
87  }
88  
89  static int gfs2_get_name(struct dentry *parent, char *name,
90  			 struct dentry *child)
91  {
92  	struct inode *dir = parent->d_inode;
93  	struct inode *inode = child->d_inode;
94  	struct gfs2_inode *dip, *ip;
95  	struct get_name_filldir gnfd;
96  	struct gfs2_holder gh;
97  	u64 offset = 0;
98  	int error;
99  
100  	if (!dir)
101  		return -EINVAL;
102  
103  	if (!S_ISDIR(dir->i_mode) || !inode)
104  		return -EINVAL;
105  
106  	dip = GFS2_I(dir);
107  	ip = GFS2_I(inode);
108  
109  	*name = 0;
110  	gnfd.inum.no_addr = ip->i_no_addr;
111  	gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
112  	gnfd.name = name;
113  
114  	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
115  	if (error)
116  		return error;
117  
118  	error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir);
119  
120  	gfs2_glock_dq_uninit(&gh);
121  
122  	if (!error && !*name)
123  		error = -ENOENT;
124  
125  	return error;
126  }
127  
128  static struct dentry *gfs2_get_parent(struct dentry *child)
129  {
130  	struct qstr dotdot;
131  	struct dentry *dentry;
132  
133  	/*
134  	 * XXX(hch): it would be a good idea to keep this around as a
135  	 *	     static variable.
136  	 */
137  	gfs2_str2qstr(&dotdot, "..");
138  
139  	dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &dotdot, 1));
140  	if (!IS_ERR(dentry))
141  		dentry->d_op = &gfs2_dops;
142  	return dentry;
143  }
144  
145  static struct dentry *gfs2_get_dentry(struct super_block *sb,
146  				      struct gfs2_inum_host *inum)
147  {
148  	struct gfs2_sbd *sdp = sb->s_fs_info;
149  	struct gfs2_holder i_gh;
150  	struct inode *inode;
151  	struct dentry *dentry;
152  	int error;
153  
154  	inode = gfs2_ilookup(sb, inum->no_addr);
155  	if (inode) {
156  		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
157  			iput(inode);
158  			return ERR_PTR(-ESTALE);
159  		}
160  		goto out_inode;
161  	}
162  
163  	error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
164  				  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
165  	if (error)
166  		return ERR_PTR(error);
167  
168  	error = gfs2_check_blk_type(sdp, inum->no_addr, GFS2_BLKST_DINODE);
169  	if (error)
170  		goto fail;
171  
172  	inode = gfs2_inode_lookup(sb, DT_UNKNOWN, inum->no_addr, 0, 0);
173  	if (IS_ERR(inode)) {
174  		error = PTR_ERR(inode);
175  		goto fail;
176  	}
177  
178  	error = gfs2_inode_refresh(GFS2_I(inode));
179  	if (error) {
180  		iput(inode);
181  		goto fail;
182  	}
183  
184  	/* Pick up the works we bypass in gfs2_inode_lookup */
185  	if (inode->i_state & I_NEW)
186  		gfs2_set_iop(inode);
187  
188  	if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
189  		iput(inode);
190  		goto fail;
191  	}
192  
193  	error = -EIO;
194  	if (GFS2_I(inode)->i_diskflags & GFS2_DIF_SYSTEM) {
195  		iput(inode);
196  		goto fail;
197  	}
198  
199  	gfs2_glock_dq_uninit(&i_gh);
200  
201  out_inode:
202  	dentry = d_obtain_alias(inode);
203  	if (!IS_ERR(dentry))
204  		dentry->d_op = &gfs2_dops;
205  	return dentry;
206  fail:
207  	gfs2_glock_dq_uninit(&i_gh);
208  	return ERR_PTR(error);
209  }
210  
211  static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
212  		int fh_len, int fh_type)
213  {
214  	struct gfs2_inum_host this;
215  	__be32 *fh = (__force __be32 *)fid->raw;
216  
217  	switch (fh_type) {
218  	case GFS2_SMALL_FH_SIZE:
219  	case GFS2_LARGE_FH_SIZE:
220  	case GFS2_OLD_FH_SIZE:
221  		this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
222  		this.no_formal_ino |= be32_to_cpu(fh[1]);
223  		this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
224  		this.no_addr |= be32_to_cpu(fh[3]);
225  		return gfs2_get_dentry(sb, &this);
226  	default:
227  		return NULL;
228  	}
229  }
230  
231  static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
232  		int fh_len, int fh_type)
233  {
234  	struct gfs2_inum_host parent;
235  	__be32 *fh = (__force __be32 *)fid->raw;
236  
237  	switch (fh_type) {
238  	case GFS2_LARGE_FH_SIZE:
239  	case GFS2_OLD_FH_SIZE:
240  		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
241  		parent.no_formal_ino |= be32_to_cpu(fh[5]);
242  		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
243  		parent.no_addr |= be32_to_cpu(fh[7]);
244  		return gfs2_get_dentry(sb, &parent);
245  	default:
246  		return NULL;
247  	}
248  }
249  
250  const struct export_operations gfs2_export_ops = {
251  	.encode_fh = gfs2_encode_fh,
252  	.fh_to_dentry = gfs2_fh_to_dentry,
253  	.fh_to_parent = gfs2_fh_to_parent,
254  	.get_name = gfs2_get_name,
255  	.get_parent = gfs2_get_parent,
256  };
257  
258