Blame view

fs/afs/mntpt.c 5.05 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
ec26815ad   David Howells   [AFS]: Clean up t...
2
  /* mountpoint management
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
   *
   * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
  #include <linux/fs.h>
  #include <linux/pagemap.h>
  #include <linux/mount.h>
  #include <linux/namei.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/gfp.h>
13fcc6837   David Howells   afs: Add fs_conte...
16
  #include <linux/fs_context.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
  #include "internal.h"
  
  
  static struct dentry *afs_mntpt_lookup(struct inode *dir,
  				       struct dentry *dentry,
00cd8dd3b   Al Viro   stop passing name...
22
  				       unsigned int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  static int afs_mntpt_open(struct inode *inode, struct file *file);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
24
  static void afs_mntpt_expiry_timed_out(struct work_struct *work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
26
  const struct file_operations afs_mntpt_file_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  	.open		= afs_mntpt_open,
6038f373a   Arnd Bergmann   llseek: automatic...
28
  	.llseek		= noop_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
30
  const struct inode_operations afs_mntpt_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  	.lookup		= afs_mntpt_lookup,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  	.readlink	= page_readlink,
416351f28   David Howells   AFS: AFS fixups
33
  	.getattr	= afs_getattr,
d3e3b7eac   David Howells   afs: Add metadata...
34
  	.listxattr	= afs_listxattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  };
bec5eb614   wanglei   AFS: Implement an...
36
  const struct inode_operations afs_autocell_inode_operations = {
bec5eb614   wanglei   AFS: Implement an...
37
38
  	.getattr	= afs_getattr,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  static LIST_HEAD(afs_vfsmounts);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
40
  static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

c1206a2c6   Adrian Bunk   fs/afs/: possible...
42
  static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

c99c2171f   David Howells   afs: Use fs_conte...
44
  static const char afs_root_volume[] = "root.cell";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
   * no valid lookup procedure on this sort of dir
   */
  static struct dentry *afs_mntpt_lookup(struct inode *dir,
  				       struct dentry *dentry,
00cd8dd3b   Al Viro   stop passing name...
50
  				       unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  {
a455589f1   Al Viro   assorted conversi...
52
  	_enter("%p,%p{%pd2}", dir, dentry, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  	return ERR_PTR(-EREMOTE);
ec26815ad   David Howells   [AFS]: Clean up t...
54
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  /*
   * no valid open procedure on this sort of dir
   */
  static int afs_mntpt_open(struct inode *inode, struct file *file)
  {
a455589f1   Al Viro   assorted conversi...
61
  	_enter("%p,%p{%pD2}", inode, file, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  	return -EREMOTE;
ec26815ad   David Howells   [AFS]: Clean up t...
63
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  /*
c99c2171f   David Howells   afs: Use fs_conte...
66
   * Set the parameters for the proposed superblock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
   */
c99c2171f   David Howells   afs: Use fs_conte...
68
  static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  {
c99c2171f   David Howells   afs: Use fs_conte...
70
71
72
73
74
  	struct afs_fs_context *ctx = fc->fs_private;
  	struct afs_super_info *src_as = AFS_FS_S(mntpt->d_sb);
  	struct afs_vnode *vnode = AFS_FS_I(d_inode(mntpt));
  	struct afs_cell *cell;
  	const char *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  	int ret;
c99c2171f   David Howells   afs: Use fs_conte...
76
77
78
79
  	if (fc->net_ns != src_as->net_ns) {
  		put_net(fc->net_ns);
  		fc->net_ns = get_net(src_as->net_ns);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

c99c2171f   David Howells   afs: Use fs_conte...
81
82
83
84
85
86
87
88
  	if (src_as->volume && src_as->volume->type == AFSVL_RWVOL) {
  		ctx->type = AFSVL_RWVOL;
  		ctx->force = true;
  	}
  	if (ctx->cell) {
  		afs_put_cell(ctx->net, ctx->cell);
  		ctx->cell = NULL;
  	}
bec5eb614   wanglei   AFS: Implement an...
89
90
  	if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
  		/* if the directory is a pseudo directory, use the d_name */
bec5eb614   wanglei   AFS: Implement an...
91
  		unsigned size = mntpt->d_name.len;
c99c2171f   David Howells   afs: Use fs_conte...
92
93
  		if (size < 2)
  			return -ENOENT;
bec5eb614   wanglei   AFS: Implement an...
94

c99c2171f   David Howells   afs: Use fs_conte...
95
  		p = mntpt->d_name.name;
bec5eb614   wanglei   AFS: Implement an...
96
  		if (mntpt->d_name.name[0] == '.') {
c99c2171f   David Howells   afs: Use fs_conte...
97
98
99
100
  			size--;
  			p++;
  			ctx->type = AFSVL_RWVOL;
  			ctx->force = true;
bec5eb614   wanglei   AFS: Implement an...
101
  		}
c99c2171f   David Howells   afs: Use fs_conte...
102
103
104
105
106
107
108
109
110
111
112
113
114
  		if (size > AFS_MAXCELLNAME)
  			return -ENAMETOOLONG;
  
  		cell = afs_lookup_cell(ctx->net, p, size, NULL, false);
  		if (IS_ERR(cell)) {
  			pr_err("kAFS: unable to lookup cell '%pd'
  ", mntpt);
  			return PTR_ERR(cell);
  		}
  		ctx->cell = cell;
  
  		ctx->volname = afs_root_volume;
  		ctx->volnamesz = sizeof(afs_root_volume) - 1;
bec5eb614   wanglei   AFS: Implement an...
115
116
  	} else {
  		/* read the contents of the AFS special symlink */
c99c2171f   David Howells   afs: Use fs_conte...
117
  		struct page *page;
2b0143b5c   David Howells   VFS: normal files...
118
  		loff_t size = i_size_read(d_inode(mntpt));
bec5eb614   wanglei   AFS: Implement an...
119
  		char *buf;
c99c2171f   David Howells   afs: Use fs_conte...
120
121
  		if (src_as->cell)
  			ctx->cell = afs_get_cell(src_as->cell);
e4086478d   David Howells   afs: Fix mountpoi...
122
  		if (size < 2 || size > PAGE_SIZE - 1)
c99c2171f   David Howells   afs: Use fs_conte...
123
  			return -EINVAL;
bec5eb614   wanglei   AFS: Implement an...
124

2b0143b5c   David Howells   VFS: normal files...
125
  		page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
c99c2171f   David Howells   afs: Use fs_conte...
126
127
  		if (IS_ERR(page))
  			return PTR_ERR(page);
bec5eb614   wanglei   AFS: Implement an...
128

f51375cd9   David Howells   afs: Add a couple...
129
130
  		if (PageError(page)) {
  			ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt);
c99c2171f   David Howells   afs: Use fs_conte...
131
132
  			put_page(page);
  			return ret;
f51375cd9   David Howells   afs: Add a couple...
133
  		}
bec5eb614   wanglei   AFS: Implement an...
134

c99c2171f   David Howells   afs: Use fs_conte...
135
  		buf = kmap(page);
e4086478d   David Howells   afs: Fix mountpoi...
136
137
138
  		ret = -EINVAL;
  		if (buf[size - 1] == '.')
  			ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
c99c2171f   David Howells   afs: Use fs_conte...
139
  		kunmap(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
140
  		put_page(page);
c99c2171f   David Howells   afs: Use fs_conte...
141
142
  		if (ret < 0)
  			return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	}
c99c2171f   David Howells   afs: Use fs_conte...
144
145
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

c99c2171f   David Howells   afs: Use fs_conte...
147
148
149
150
151
152
153
154
  /*
   * create a vfsmount to be automounted
   */
  static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
  {
  	struct fs_context *fc;
  	struct vfsmount *mnt;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155

c99c2171f   David Howells   afs: Use fs_conte...
156
  	BUG_ON(!d_inode(mntpt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

c99c2171f   David Howells   afs: Use fs_conte...
158
159
160
161
162
163
164
165
166
167
168
169
  	fc = fs_context_for_submount(&afs_fs_type, mntpt);
  	if (IS_ERR(fc))
  		return ERR_CAST(fc);
  
  	ret = afs_mntpt_set_params(fc, mntpt);
  	if (!ret)
  		mnt = fc_mount(fc);
  	else
  		mnt = ERR_PTR(ret);
  
  	put_fs_context(fc);
  	return mnt;
ec26815ad   David Howells   [AFS]: Clean up t...
170
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  /*
d18610b0c   David Howells   AFS: Use d_automo...
173
   * handle an automount point
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
   */
d18610b0c   David Howells   AFS: Use d_automo...
175
  struct vfsmount *afs_d_automount(struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
  {
  	struct vfsmount *newmnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178

a455589f1   Al Viro   assorted conversi...
179
  	_enter("{%pd}", path->dentry);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
180

d18610b0c   David Howells   AFS: Use d_automo...
181
182
183
  	newmnt = afs_mntpt_do_automount(path->dentry);
  	if (IS_ERR(newmnt))
  		return newmnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

ea5b778a8   David Howells   Unexport do_add_m...
185
186
187
188
  	mntget(newmnt); /* prevent immediate expiration */
  	mnt_set_expiry(newmnt, &afs_vfsmounts);
  	queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer,
  			   afs_mntpt_expiry_timeout * HZ);
5ffc2836a   Al Viro   vfs: kill ->mnt_d...
189
  	_leave(" = %p", newmnt);
ea5b778a8   David Howells   Unexport do_add_m...
190
  	return newmnt;
ec26815ad   David Howells   [AFS]: Clean up t...
191
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
  /*
   * handle mountpoint expiry timer going off
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
196
  static void afs_mntpt_expiry_timed_out(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
198
199
200
201
  	_enter("");
  
  	if (!list_empty(&afs_vfsmounts)) {
  		mark_mounts_for_expiry(&afs_vfsmounts);
0ad53eeef   Tejun Heo   afs: add afs_wq a...
202
203
  		queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer,
  				   afs_mntpt_expiry_timeout * HZ);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
204
205
206
207
  	}
  
  	_leave("");
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
209
210
211
212
213
214
  /*
   * kill the AFS mountpoint timer if it's still running
   */
  void afs_mntpt_kill_timer(void)
  {
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
216
  	ASSERT(list_empty(&afs_vfsmounts));
0ad53eeef   Tejun Heo   afs: add afs_wq a...
217
  	cancel_delayed_work_sync(&afs_mntpt_expiry_timer);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
218
  }