Blame view

fs/gfs2/export.c 4.64 KB
7336d0e65   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
b3b94faa5   David Teigland   [GFS2] The core o...
2
3
  /*
   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3a8a9a103   Steven Whitehouse   [GFS2] Update cop...
4
   * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
b3b94faa5   David Teigland   [GFS2] The core o...
5
   */
b3b94faa5   David Teigland   [GFS2] The core o...
6
7
8
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
9
  #include <linux/exportfs.h>
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
10
  #include <linux/gfs2_ondisk.h>
71b86f562   Steven Whitehouse   [GFS2] Further up...
11
  #include <linux/crc32.h>
b3b94faa5   David Teigland   [GFS2] The core o...
12
13
  
  #include "gfs2.h"
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
14
  #include "incore.h"
b3b94faa5   David Teigland   [GFS2] The core o...
15
16
17
18
  #include "dir.h"
  #include "glock.h"
  #include "glops.h"
  #include "inode.h"
b27605837   Steven Whitehouse   GFS2: Rationalise...
19
  #include "super.h"
b3b94faa5   David Teigland   [GFS2] The core o...
20
  #include "rgrp.h"
c752666c1   Steven Whitehouse   [GFS2] Fix bug in...
21
  #include "util.h"
b3b94faa5   David Teigland   [GFS2] The core o...
22

bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
23
  #define GFS2_SMALL_FH_SIZE 4
35dcc52e3   Wendy Cheng   [GFS2] Remove i_m...
24
  #define GFS2_LARGE_FH_SIZE 8
3ebf44902   Steven Whitehouse   [GFS2] Accept old...
25
  #define GFS2_OLD_FH_SIZE 10
bb8d8a6f5   Steven Whitehouse   [GFS2] Fix sign p...
26

b0b0382bb   Al Viro   ->encode_fh() API...
27
28
  static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
  			  struct inode *parent)
b3b94faa5   David Teigland   [GFS2] The core o...
29
  {
b44b84d76   Al Viro   [GFS2] gfs2 misc ...
30
  	__be32 *fh = (__force __be32 *)p;
c9fd43078   Steven Whitehouse   [GFS2] Tidy up mo...
31
  	struct super_block *sb = inode->i_sb;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
32
  	struct gfs2_inode *ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
33

b0b0382bb   Al Viro   ->encode_fh() API...
34
  	if (parent && (*len < GFS2_LARGE_FH_SIZE)) {
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
35
  		*len = GFS2_LARGE_FH_SIZE;
94e07a759   Namjae Jeon   fs: encode_fh: re...
36
  		return FILEID_INVALID;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
37
38
  	} else if (*len < GFS2_SMALL_FH_SIZE) {
  		*len = GFS2_SMALL_FH_SIZE;
94e07a759   Namjae Jeon   fs: encode_fh: re...
39
  		return FILEID_INVALID;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
40
  	}
b3b94faa5   David Teigland   [GFS2] The core o...
41

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
42
43
44
45
  	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  	fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
  	fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
5acd39673   Steven Whitehouse   [GFS2] Some furth...
46
  	*len = GFS2_SMALL_FH_SIZE;
b3b94faa5   David Teigland   [GFS2] The core o...
47

2b0143b5c   David Howells   VFS: normal files...
48
  	if (!parent || inode == d_inode(sb->s_root))
b3b94faa5   David Teigland   [GFS2] The core o...
49
  		return *len;
b0b0382bb   Al Viro   ->encode_fh() API...
50
  	ip = GFS2_I(parent);
b3b94faa5   David Teigland   [GFS2] The core o...
51

dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
52
53
54
55
  	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
  	fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
  	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
  	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
5acd39673   Steven Whitehouse   [GFS2] Some furth...
56
  	*len = GFS2_LARGE_FH_SIZE;
b3b94faa5   David Teigland   [GFS2] The core o...
57

b3b94faa5   David Teigland   [GFS2] The core o...
58
59
60
61
  	return *len;
  }
  
  struct get_name_filldir {
d81a8ef59   Al Viro   [readdir] convert...
62
  	struct dir_context ctx;
629a21e7e   Al Viro   [GFS2] split and ...
63
  	struct gfs2_inum_host inum;
b3b94faa5   David Teigland   [GFS2] The core o...
64
65
  	char *name;
  };
ac7576f4b   Miklos Szeredi   vfs: make first a...
66
67
68
  static int get_name_filldir(struct dir_context *ctx, const char *name,
  			    int length, loff_t offset, u64 inum,
  			    unsigned int type)
b3b94faa5   David Teigland   [GFS2] The core o...
69
  {
ac7576f4b   Miklos Szeredi   vfs: make first a...
70
71
  	struct get_name_filldir *gnfd =
  		container_of(ctx, struct get_name_filldir, ctx);
b3b94faa5   David Teigland   [GFS2] The core o...
72

3699e3a44   Steven Whitehouse   [GFS2] Clean up/s...
73
  	if (inum != gnfd->inum.no_addr)
b3b94faa5   David Teigland   [GFS2] The core o...
74
75
76
77
78
79
80
81
82
83
84
  		return 0;
  
  	memcpy(gnfd->name, name, length);
  	gnfd->name[length] = 0;
  
  	return 1;
  }
  
  static int gfs2_get_name(struct dentry *parent, char *name,
  			 struct dentry *child)
  {
2b0143b5c   David Howells   VFS: normal files...
85
86
  	struct inode *dir = d_inode(parent);
  	struct inode *inode = d_inode(child);
b3b94faa5   David Teigland   [GFS2] The core o...
87
  	struct gfs2_inode *dip, *ip;
ac6614b76   Al Viro   [readdir] constif...
88
89
90
91
  	struct get_name_filldir gnfd = {
  		.ctx.actor = get_name_filldir,
  		.name = name
  	};
b3b94faa5   David Teigland   [GFS2] The core o...
92
  	struct gfs2_holder gh;
b3b94faa5   David Teigland   [GFS2] The core o...
93
  	int error;
dfe4d34b3   Bob Peterson   GFS2: Add readahe...
94
  	struct file_ra_state f_ra = { .start = 0 };
b3b94faa5   David Teigland   [GFS2] The core o...
95
96
97
  
  	if (!dir)
  		return -EINVAL;
b3b94faa5   David Teigland   [GFS2] The core o...
98
99
  	if (!S_ISDIR(dir->i_mode) || !inode)
  		return -EINVAL;
feaa7bba0   Steven Whitehouse   [GFS2] Fix unlink...
100
101
  	dip = GFS2_I(dir);
  	ip = GFS2_I(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
102
103
  
  	*name = 0;
dbb7cae2a   Steven Whitehouse   [GFS2] Clean up i...
104
105
  	gnfd.inum.no_addr = ip->i_no_addr;
  	gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
b3b94faa5   David Teigland   [GFS2] The core o...
106
107
108
109
  
  	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
  	if (error)
  		return error;
d81a8ef59   Al Viro   [readdir] convert...
110
  	error = gfs2_dir_read(dir, &gnfd.ctx, &f_ra);
b3b94faa5   David Teigland   [GFS2] The core o...
111
112
113
114
115
116
117
118
119
120
121
  
  	gfs2_glock_dq_uninit(&gh);
  
  	if (!error && !*name)
  		error = -ENOENT;
  
  	return error;
  }
  
  static struct dentry *gfs2_get_parent(struct dentry *child)
  {
2b0143b5c   David Howells   VFS: normal files...
122
  	return d_obtain_alias(gfs2_lookupi(d_inode(child), &gfs2_qdotdot, 1));
b3b94faa5   David Teigland   [GFS2] The core o...
123
  }
34c0d1542   Christoph Hellwig   gfs2: new export ops
124
  static struct dentry *gfs2_get_dentry(struct super_block *sb,
acf7e2444   Steven Whitehouse   GFS2: Be extra ca...
125
  				      struct gfs2_inum_host *inum)
b3b94faa5   David Teigland   [GFS2] The core o...
126
  {
5c676f6d3   Steven Whitehouse   [GFS2] Macros rem...
127
  	struct gfs2_sbd *sdp = sb->s_fs_info;
b3b94faa5   David Teigland   [GFS2] The core o...
128
  	struct inode *inode;
b3b94faa5   David Teigland   [GFS2] The core o...
129

6bdcadea7   Andreas Gruenbacher   gfs2: Minor gfs2_...
130
131
132
  	if (!inum->no_formal_ino)
  		return ERR_PTR(-ESTALE);
  	inode = gfs2_lookup_by_inum(sdp, inum->no_addr, inum->no_formal_ino,
044b9414c   Steven Whitehouse   GFS2: Fix inode d...
133
134
135
  				    GFS2_BLKST_DINODE);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
41ced6dcf   Al Viro   switch gfs2, clos...
136
  	return d_obtain_alias(inode);
b3b94faa5   David Teigland   [GFS2] The core o...
137
  }
34c0d1542   Christoph Hellwig   gfs2: new export ops
138
139
140
141
142
143
144
145
146
147
  static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	struct gfs2_inum_host this;
  	__be32 *fh = (__force __be32 *)fid->raw;
  
  	switch (fh_type) {
  	case GFS2_SMALL_FH_SIZE:
  	case GFS2_LARGE_FH_SIZE:
  	case GFS2_OLD_FH_SIZE:
35c2a7f49   Hugh Dickins   tmpfs,ceph,gfs2,i...
148
149
  		if (fh_len < GFS2_SMALL_FH_SIZE)
  			return NULL;
34c0d1542   Christoph Hellwig   gfs2: new export ops
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  		this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
  		this.no_formal_ino |= be32_to_cpu(fh[1]);
  		this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
  		this.no_addr |= be32_to_cpu(fh[3]);
  		return gfs2_get_dentry(sb, &this);
  	default:
  		return NULL;
  	}
  }
  
  static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
  		int fh_len, int fh_type)
  {
  	struct gfs2_inum_host parent;
  	__be32 *fh = (__force __be32 *)fid->raw;
  
  	switch (fh_type) {
  	case GFS2_LARGE_FH_SIZE:
  	case GFS2_OLD_FH_SIZE:
35c2a7f49   Hugh Dickins   tmpfs,ceph,gfs2,i...
169
170
  		if (fh_len < GFS2_LARGE_FH_SIZE)
  			return NULL;
34c0d1542   Christoph Hellwig   gfs2: new export ops
171
172
173
174
175
176
177
178
179
  		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
  		parent.no_formal_ino |= be32_to_cpu(fh[5]);
  		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
  		parent.no_addr |= be32_to_cpu(fh[7]);
  		return gfs2_get_dentry(sb, &parent);
  	default:
  		return NULL;
  	}
  }
396551644   Christoph Hellwig   exportfs: make st...
180
  const struct export_operations gfs2_export_ops = {
b3b94faa5   David Teigland   [GFS2] The core o...
181
  	.encode_fh = gfs2_encode_fh,
34c0d1542   Christoph Hellwig   gfs2: new export ops
182
183
  	.fh_to_dentry = gfs2_fh_to_dentry,
  	.fh_to_parent = gfs2_fh_to_parent,
b3b94faa5   David Teigland   [GFS2] The core o...
184
185
  	.get_name = gfs2_get_name,
  	.get_parent = gfs2_get_parent,
b3b94faa5   David Teigland   [GFS2] The core o...
186
  };