Blame view

fs/afs/mntpt.c 5.19 KB
ec26815ad   David Howells   [AFS]: Clean up t...
1
  /* mountpoint management
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
   *
   * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  #include <linux/fs.h>
  #include <linux/pagemap.h>
  #include <linux/mount.h>
  #include <linux/namei.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
  #include "internal.h"
  
  
  static struct dentry *afs_mntpt_lookup(struct inode *dir,
  				       struct dentry *dentry,
00cd8dd3b   Al Viro   stop passing name...
25
  				       unsigned int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  static int afs_mntpt_open(struct inode *inode, struct file *file);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
27
  static void afs_mntpt_expiry_timed_out(struct work_struct *work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
   * 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...
52
  				       unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  {
a455589f1   Al Viro   assorted conversi...
54
  	_enter("%p,%p{%pd2}", dir, dentry, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  	return ERR_PTR(-EREMOTE);
ec26815ad   David Howells   [AFS]: Clean up t...
56
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
  /*
   * 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...
63
  	_enter("%p,%p{%pD2}", inode, file, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  	return -EREMOTE;
ec26815ad   David Howells   [AFS]: Clean up t...
65
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
71
72
73
  /*
   * create a vfsmount to be automounted
   */
  static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
  {
  	struct afs_super_info *super;
  	struct vfsmount *mnt;
bec5eb614   wanglei   AFS: Implement an...
74
  	struct afs_vnode *vnode;
083fd8b21   David Howells   AFS: Don't pass e...
75
  	struct page *page;
bec5eb614   wanglei   AFS: Implement an...
76
77
  	char *devname, *options;
  	bool rwpath = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  	int ret;
a455589f1   Al Viro   assorted conversi...
79
  	_enter("{%pd}", mntpt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

2b0143b5c   David Howells   VFS: normal files...
81
  	BUG_ON(!d_inode(mntpt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
  	ret = -ENOMEM;
  	devname = (char *) get_zeroed_page(GFP_KERNEL);
  	if (!devname)
083fd8b21   David Howells   AFS: Don't pass e...
86
  		goto error_no_devname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
  
  	options = (char *) get_zeroed_page(GFP_KERNEL);
  	if (!options)
083fd8b21   David Howells   AFS: Don't pass e...
90
  		goto error_no_options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91

2b0143b5c   David Howells   VFS: normal files...
92
  	vnode = AFS_FS_I(d_inode(mntpt));
bec5eb614   wanglei   AFS: Implement an...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  	if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
  		/* if the directory is a pseudo directory, use the d_name */
  		static const char afs_root_cell[] = ":root.cell.";
  		unsigned size = mntpt->d_name.len;
  
  		ret = -ENOENT;
  		if (size < 2 || size > AFS_MAXCELLNAME)
  			goto error_no_page;
  
  		if (mntpt->d_name.name[0] == '.') {
  			devname[0] = '#';
  			memcpy(devname + 1, mntpt->d_name.name, size - 1);
  			memcpy(devname + size, afs_root_cell,
  			       sizeof(afs_root_cell));
  			rwpath = true;
  		} else {
  			devname[0] = '%';
  			memcpy(devname + 1, mntpt->d_name.name, size);
  			memcpy(devname + size + 1, afs_root_cell,
  			       sizeof(afs_root_cell));
  		}
  	} else {
  		/* read the contents of the AFS special symlink */
2b0143b5c   David Howells   VFS: normal files...
116
  		loff_t size = i_size_read(d_inode(mntpt));
bec5eb614   wanglei   AFS: Implement an...
117
118
119
120
121
  		char *buf;
  
  		ret = -EINVAL;
  		if (size > PAGE_SIZE - 1)
  			goto error_no_page;
2b0143b5c   David Howells   VFS: normal files...
122
  		page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
bec5eb614   wanglei   AFS: Implement an...
123
124
125
126
127
128
129
130
  		if (IS_ERR(page)) {
  			ret = PTR_ERR(page);
  			goto error_no_page;
  		}
  
  		ret = -EIO;
  		if (PageError(page))
  			goto error;
da4aa36d0   Cong Wang   afs: remove the s...
131
  		buf = kmap_atomic(page);
bec5eb614   wanglei   AFS: Implement an...
132
  		memcpy(devname, buf, size);
da4aa36d0   Cong Wang   afs: remove the s...
133
  		kunmap_atomic(buf);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
134
  		put_page(page);
bec5eb614   wanglei   AFS: Implement an...
135
  		page = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
  	/* work out what options we want */
  	super = AFS_FS_S(mntpt->d_sb);
  	memcpy(options, "cell=", 5);
  	strcpy(options + 5, super->volume->cell->name);
bec5eb614   wanglei   AFS: Implement an...
141
  	if (super->volume->type == AFSVL_RWVOL || rwpath)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
  		strcat(options, ",rwpath");
  
  	/* try and do the mount */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
145
  	_debug("--- attempting mount %s -o %s ---", devname, options);
93faccbbf   Eric W. Biederman   fs: Better permis...
146
  	mnt = vfs_submount(mntpt, &afs_fs_type, devname, options);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
147
  	_debug("--- mount result %p ---", mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
  
  	free_page((unsigned long) devname);
  	free_page((unsigned long) options);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
151
  	_leave(" = %p", mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  	return mnt;
ec26815ad   David Howells   [AFS]: Clean up t...
153
  error:
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
154
  	put_page(page);
083fd8b21   David Howells   AFS: Don't pass e...
155
156
157
158
159
  error_no_page:
  	free_page((unsigned long) options);
  error_no_options:
  	free_page((unsigned long) devname);
  error_no_devname:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
160
  	_leave(" = %d", ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  	return ERR_PTR(ret);
ec26815ad   David Howells   [AFS]: Clean up t...
162
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  /*
d18610b0c   David Howells   AFS: Use d_automo...
165
   * handle an automount point
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
   */
d18610b0c   David Howells   AFS: Use d_automo...
167
  struct vfsmount *afs_d_automount(struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  {
  	struct vfsmount *newmnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

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

d18610b0c   David Howells   AFS: Use d_automo...
173
174
175
  	newmnt = afs_mntpt_do_automount(path->dentry);
  	if (IS_ERR(newmnt))
  		return newmnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176

ea5b778a8   David Howells   Unexport do_add_m...
177
178
179
180
  	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...
181
  	_leave(" = %p", newmnt);
ea5b778a8   David Howells   Unexport do_add_m...
182
  	return newmnt;
ec26815ad   David Howells   [AFS]: Clean up t...
183
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

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

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
201
202
203
204
205
206
  /*
   * 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
207

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