Blame view

fs/pnode.c 8.96 KB
07b20889e   Ram Pai   [PATCH] beginning...
1
2
3
4
5
6
7
8
  /*
   *  linux/fs/pnode.c
   *
   * (C) Copyright IBM Corporation 2005.
   *	Released under GPL v2.
   *	Author : Ram Pai (linuxram@us.ibm.com)
   *
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
9
  #include <linux/mnt_namespace.h>
07b20889e   Ram Pai   [PATCH] beginning...
10
11
  #include <linux/mount.h>
  #include <linux/fs.h>
132c94e31   Eric W. Biederman   vfs: Carefully pr...
12
  #include <linux/nsproxy.h>
6d59e7f58   Al Viro   [PATCH] move a bu...
13
  #include "internal.h"
07b20889e   Ram Pai   [PATCH] beginning...
14
  #include "pnode.h"
03e06e68f   Ram Pai   [PATCH] introduce...
15
  /* return the next shared peer mount of @p */
c937135d9   Al Viro   vfs: spread struc...
16
  static inline struct mount *next_peer(struct mount *p)
03e06e68f   Ram Pai   [PATCH] introduce...
17
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
18
  	return list_entry(p->mnt_share.next, struct mount, mnt_share);
03e06e68f   Ram Pai   [PATCH] introduce...
19
  }
c937135d9   Al Viro   vfs: spread struc...
20
  static inline struct mount *first_slave(struct mount *p)
5afe00221   Ram Pai   [PATCH] handling ...
21
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
22
  	return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave);
5afe00221   Ram Pai   [PATCH] handling ...
23
  }
c937135d9   Al Viro   vfs: spread struc...
24
  static inline struct mount *next_slave(struct mount *p)
5afe00221   Ram Pai   [PATCH] handling ...
25
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
26
  	return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
5afe00221   Ram Pai   [PATCH] handling ...
27
  }
6fc7871fe   Al Viro   vfs: spread struc...
28
29
30
  static struct mount *get_peer_under_root(struct mount *mnt,
  					 struct mnt_namespace *ns,
  					 const struct path *root)
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
31
  {
6fc7871fe   Al Viro   vfs: spread struc...
32
  	struct mount *m = mnt;
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
33
34
35
  
  	do {
  		/* Check the namespace first for optimization */
143c8c91c   Al Viro   vfs: mnt_ns moved...
36
  		if (m->mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root))
6fc7871fe   Al Viro   vfs: spread struc...
37
  			return m;
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
38

c937135d9   Al Viro   vfs: spread struc...
39
  		m = next_peer(m);
6fc7871fe   Al Viro   vfs: spread struc...
40
  	} while (m != mnt);
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
41
42
43
44
45
46
47
48
49
50
  
  	return NULL;
  }
  
  /*
   * Get ID of closest dominating peer group having a representative
   * under the given root.
   *
   * Caller must hold namespace_sem
   */
6fc7871fe   Al Viro   vfs: spread struc...
51
  int get_dominating_id(struct mount *mnt, const struct path *root)
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
52
  {
6fc7871fe   Al Viro   vfs: spread struc...
53
  	struct mount *m;
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
54

32301920f   Al Viro   vfs: and now we c...
55
  	for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
143c8c91c   Al Viro   vfs: mnt_ns moved...
56
  		struct mount *d = get_peer_under_root(m, mnt->mnt_ns, root);
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
57
  		if (d)
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
58
  			return d->mnt_group_id;
97e7e0f71   Miklos Szeredi   [patch 7/7] vfs: ...
59
60
61
62
  	}
  
  	return 0;
  }
6fc7871fe   Al Viro   vfs: spread struc...
63
  static int do_make_slave(struct mount *mnt)
a58b0eb8e   Ram Pai   [PATCH] introduce...
64
  {
32301920f   Al Viro   vfs: and now we c...
65
  	struct mount *peer_mnt = mnt, *master = mnt->mnt_master;
d10e8def0   Al Viro   vfs: take mnt_mas...
66
  	struct mount *slave_mnt;
a58b0eb8e   Ram Pai   [PATCH] introduce...
67
68
69
  
  	/*
  	 * slave 'mnt' to a peer mount that has the
796a6b521   Al Viro   Kill CL_PROPAGATI...
70
  	 * same root dentry. If none is available then
a58b0eb8e   Ram Pai   [PATCH] introduce...
71
72
  	 * slave it to anything that is available.
  	 */
c937135d9   Al Viro   vfs: spread struc...
73
  	while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
6fc7871fe   Al Viro   vfs: spread struc...
74
  	       peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ;
a58b0eb8e   Ram Pai   [PATCH] introduce...
75
76
  
  	if (peer_mnt == mnt) {
c937135d9   Al Viro   vfs: spread struc...
77
  		peer_mnt = next_peer(mnt);
a58b0eb8e   Ram Pai   [PATCH] introduce...
78
79
80
  		if (peer_mnt == mnt)
  			peer_mnt = NULL;
  	}
5d477b607   Takashi Iwai   vfs: Fix invalid ...
81
82
  	if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) &&
  	    list_empty(&mnt->mnt_share))
6fc7871fe   Al Viro   vfs: spread struc...
83
  		mnt_release_group_id(mnt);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
84

6776db3d3   Al Viro   vfs: take mnt_sha...
85
  	list_del_init(&mnt->mnt_share);
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
86
  	mnt->mnt_group_id = 0;
a58b0eb8e   Ram Pai   [PATCH] introduce...
87
88
89
90
91
  
  	if (peer_mnt)
  		master = peer_mnt;
  
  	if (master) {
6776db3d3   Al Viro   vfs: take mnt_sha...
92
  		list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
32301920f   Al Viro   vfs: and now we c...
93
  			slave_mnt->mnt_master = master;
6776db3d3   Al Viro   vfs: take mnt_sha...
94
95
96
  		list_move(&mnt->mnt_slave, &master->mnt_slave_list);
  		list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
  		INIT_LIST_HEAD(&mnt->mnt_slave_list);
a58b0eb8e   Ram Pai   [PATCH] introduce...
97
  	} else {
6776db3d3   Al Viro   vfs: take mnt_sha...
98
  		struct list_head *p = &mnt->mnt_slave_list;
a58b0eb8e   Ram Pai   [PATCH] introduce...
99
  		while (!list_empty(p)) {
b5e618181   Pavel Emelianov   Introduce a handy...
100
                          slave_mnt = list_first_entry(p,
6776db3d3   Al Viro   vfs: take mnt_sha...
101
102
  					struct mount, mnt_slave);
  			list_del_init(&slave_mnt->mnt_slave);
a58b0eb8e   Ram Pai   [PATCH] introduce...
103
104
105
  			slave_mnt->mnt_master = NULL;
  		}
  	}
32301920f   Al Viro   vfs: and now we c...
106
  	mnt->mnt_master = master;
fc7be130c   Al Viro   vfs: switch pnode...
107
  	CLEAR_MNT_SHARED(mnt);
a58b0eb8e   Ram Pai   [PATCH] introduce...
108
109
  	return 0;
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
110
111
112
  /*
   * vfsmount lock must be held for write
   */
0f0afb1dc   Al Viro   vfs: spread struc...
113
  void change_mnt_propagation(struct mount *mnt, int type)
07b20889e   Ram Pai   [PATCH] beginning...
114
  {
03e06e68f   Ram Pai   [PATCH] introduce...
115
  	if (type == MS_SHARED) {
b90fa9ae8   Ram Pai   [PATCH] shared mo...
116
  		set_mnt_shared(mnt);
a58b0eb8e   Ram Pai   [PATCH] introduce...
117
118
  		return;
  	}
6fc7871fe   Al Viro   vfs: spread struc...
119
  	do_make_slave(mnt);
a58b0eb8e   Ram Pai   [PATCH] introduce...
120
  	if (type != MS_SLAVE) {
6776db3d3   Al Viro   vfs: take mnt_sha...
121
  		list_del_init(&mnt->mnt_slave);
d10e8def0   Al Viro   vfs: take mnt_mas...
122
  		mnt->mnt_master = NULL;
9676f0c63   Ram Pai   [PATCH] unbindabl...
123
  		if (type == MS_UNBINDABLE)
0f0afb1dc   Al Viro   vfs: spread struc...
124
  			mnt->mnt.mnt_flags |= MNT_UNBINDABLE;
0b03cfb25   Andries E. Brouwer   MNT_UNBINDABLE fix
125
  		else
0f0afb1dc   Al Viro   vfs: spread struc...
126
  			mnt->mnt.mnt_flags &= ~MNT_UNBINDABLE;
03e06e68f   Ram Pai   [PATCH] introduce...
127
  	}
07b20889e   Ram Pai   [PATCH] beginning...
128
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
129
130
131
132
133
  
  /*
   * get the next mount in the propagation tree.
   * @m: the mount seen last
   * @origin: the original mount from where the tree walk initiated
796a6b521   Al Viro   Kill CL_PROPAGATI...
134
135
136
137
138
   *
   * Note that peer groups form contiguous segments of slave lists.
   * We rely on that in get_source() to be able to find out if
   * vfsmount found while iterating with propagation_next() is
   * a peer of one we'd found earlier.
b90fa9ae8   Ram Pai   [PATCH] shared mo...
139
   */
c937135d9   Al Viro   vfs: spread struc...
140
141
  static struct mount *propagation_next(struct mount *m,
  					 struct mount *origin)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
142
  {
5afe00221   Ram Pai   [PATCH] handling ...
143
  	/* are there any slaves of this mount? */
143c8c91c   Al Viro   vfs: mnt_ns moved...
144
  	if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
5afe00221   Ram Pai   [PATCH] handling ...
145
146
147
  		return first_slave(m);
  
  	while (1) {
32301920f   Al Viro   vfs: and now we c...
148
  		struct mount *master = m->mnt_master;
5afe00221   Ram Pai   [PATCH] handling ...
149

32301920f   Al Viro   vfs: and now we c...
150
  		if (master == origin->mnt_master) {
c937135d9   Al Viro   vfs: spread struc...
151
152
  			struct mount *next = next_peer(m);
  			return (next == origin) ? NULL : next;
6776db3d3   Al Viro   vfs: take mnt_sha...
153
  		} else if (m->mnt_slave.next != &master->mnt_slave_list)
5afe00221   Ram Pai   [PATCH] handling ...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  			return next_slave(m);
  
  		/* back at master */
  		m = master;
  	}
  }
  
  /*
   * return the source mount to be used for cloning
   *
   * @dest 	the current destination mount
   * @last_dest  	the last seen destination mount
   * @last_src  	the last seen source mount
   * @type	return CL_SLAVE if the new mount has to be
   * 		cloned as a slave.
   */
c937135d9   Al Viro   vfs: spread struc...
170
171
172
173
  static struct mount *get_source(struct mount *dest,
  				struct mount *last_dest,
  				struct mount *last_src,
  				int *type)
5afe00221   Ram Pai   [PATCH] handling ...
174
  {
c937135d9   Al Viro   vfs: spread struc...
175
176
  	struct mount *p_last_src = NULL;
  	struct mount *p_last_dest = NULL;
5afe00221   Ram Pai   [PATCH] handling ...
177

32301920f   Al Viro   vfs: and now we c...
178
  	while (last_dest != dest->mnt_master) {
5afe00221   Ram Pai   [PATCH] handling ...
179
180
  		p_last_dest = last_dest;
  		p_last_src = last_src;
32301920f   Al Viro   vfs: and now we c...
181
182
  		last_dest = last_dest->mnt_master;
  		last_src = last_src->mnt_master;
5afe00221   Ram Pai   [PATCH] handling ...
183
184
185
186
187
  	}
  
  	if (p_last_dest) {
  		do {
  			p_last_dest = next_peer(p_last_dest);
143c8c91c   Al Viro   vfs: mnt_ns moved...
188
  		} while (IS_MNT_NEW(p_last_dest));
796a6b521   Al Viro   Kill CL_PROPAGATI...
189
190
191
192
193
  		/* is that a peer of the earlier? */
  		if (dest == p_last_dest) {
  			*type = CL_MAKE_SHARED;
  			return p_last_src;
  		}
5afe00221   Ram Pai   [PATCH] handling ...
194
  	}
796a6b521   Al Viro   Kill CL_PROPAGATI...
195
196
197
  	/* slave of the earlier, then */
  	*type = CL_SLAVE;
  	/* beginning of peer group among the slaves? */
fc7be130c   Al Viro   vfs: switch pnode...
198
  	if (IS_MNT_SHARED(dest))
796a6b521   Al Viro   Kill CL_PROPAGATI...
199
200
  		*type |= CL_MAKE_SHARED;
  	return last_src;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  }
  
  /*
   * mount 'source_mnt' under the destination 'dest_mnt' at
   * dentry 'dest_dentry'. And propagate that mount to
   * all the peer and slave mounts of 'dest_mnt'.
   * Link all the new mounts into a propagation tree headed at
   * source_mnt. Also link all the new mounts using ->mnt_list
   * headed at source_mnt's ->mnt_list
   *
   * @dest_mnt: destination mount.
   * @dest_dentry: destination dentry.
   * @source_mnt: source mount.
   * @tree_list : list of heads of trees to be attached.
   */
84d17192d   Al Viro   get rid of full-h...
216
  int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
a8d56d8e4   Al Viro   vfs: spread struc...
217
  		    struct mount *source_mnt, struct list_head *tree_list)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
218
  {
132c94e31   Eric W. Biederman   vfs: Carefully pr...
219
  	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
c937135d9   Al Viro   vfs: spread struc...
220
  	struct mount *m, *child;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
221
  	int ret = 0;
a8d56d8e4   Al Viro   vfs: spread struc...
222
223
  	struct mount *prev_dest_mnt = dest_mnt;
  	struct mount *prev_src_mnt  = source_mnt;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
224
  	LIST_HEAD(tmp_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
225

a8d56d8e4   Al Viro   vfs: spread struc...
226
227
  	for (m = propagation_next(dest_mnt, dest_mnt); m;
  			m = propagation_next(m, dest_mnt)) {
5afe00221   Ram Pai   [PATCH] handling ...
228
  		int type;
c937135d9   Al Viro   vfs: spread struc...
229
  		struct mount *source;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
230

143c8c91c   Al Viro   vfs: mnt_ns moved...
231
  		if (IS_MNT_NEW(m))
b90fa9ae8   Ram Pai   [PATCH] shared mo...
232
  			continue;
5afe00221   Ram Pai   [PATCH] handling ...
233
  		source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
234

132c94e31   Eric W. Biederman   vfs: Carefully pr...
235
236
237
  		/* Notice when we are propagating across user namespaces */
  		if (m->mnt_ns->user_ns != user_ns)
  			type |= CL_UNPRIVILEGED;
be34d1a3b   David Howells   VFS: Make clone_m...
238
239
240
  		child = copy_tree(source, source->mnt.mnt_root, type);
  		if (IS_ERR(child)) {
  			ret = PTR_ERR(child);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
241
242
243
  			list_splice(tree_list, tmp_list.prev);
  			goto out;
  		}
84d17192d   Al Viro   get rid of full-h...
244
245
  		if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
  			mnt_set_mountpoint(m, dest_mp, child);
1b8e5564b   Al Viro   vfs: the first sp...
246
  			list_add_tail(&child->mnt_hash, tree_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
247
248
249
250
251
  		} else {
  			/*
  			 * This can happen if the parent mount was bind mounted
  			 * on some subdirectory of a shared/slave mount.
  			 */
1b8e5564b   Al Viro   vfs: the first sp...
252
  			list_add_tail(&child->mnt_hash, &tmp_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
253
254
  		}
  		prev_dest_mnt = m;
c937135d9   Al Viro   vfs: spread struc...
255
  		prev_src_mnt  = child;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
256
257
  	}
  out:
719ea2fbb   Al Viro   new helpers: lock...
258
  	lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
259
  	while (!list_empty(&tmp_list)) {
1b8e5564b   Al Viro   vfs: the first sp...
260
  		child = list_first_entry(&tmp_list, struct mount, mnt_hash);
328e6d901   Al Viro   switch unlock_mou...
261
  		umount_tree(child, 0);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
262
  	}
719ea2fbb   Al Viro   new helpers: lock...
263
  	unlock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
264
265
  	return ret;
  }
a05964f39   Ram Pai   [PATCH] shared mo...
266
267
268
269
  
  /*
   * return true if the refcount is greater than count
   */
1ab597386   Al Viro   vfs: spread struc...
270
  static inline int do_refcount_check(struct mount *mnt, int count)
a05964f39   Ram Pai   [PATCH] shared mo...
271
  {
aba809cf0   Al Viro   namespace.c: get ...
272
  	return mnt_get_count(mnt) > count;
a05964f39   Ram Pai   [PATCH] shared mo...
273
274
275
276
277
278
279
280
281
  }
  
  /*
   * check if the mount 'mnt' can be unmounted successfully.
   * @mnt: the mount to be checked for unmount
   * NOTE: unmounting 'mnt' would naturally propagate to all
   * other mounts its parent propagates to.
   * Check if any of these mounts that **do not have submounts**
   * have more references than 'refcnt'. If so return busy.
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
282
   *
b3e19d924   Nick Piggin   fs: scale mntget/...
283
   * vfsmount lock must be held for write
a05964f39   Ram Pai   [PATCH] shared mo...
284
   */
1ab597386   Al Viro   vfs: spread struc...
285
  int propagate_mount_busy(struct mount *mnt, int refcnt)
a05964f39   Ram Pai   [PATCH] shared mo...
286
  {
c937135d9   Al Viro   vfs: spread struc...
287
  	struct mount *m, *child;
0714a5338   Al Viro   vfs: now it can b...
288
  	struct mount *parent = mnt->mnt_parent;
a05964f39   Ram Pai   [PATCH] shared mo...
289
  	int ret = 0;
0714a5338   Al Viro   vfs: now it can b...
290
  	if (mnt == parent)
a05964f39   Ram Pai   [PATCH] shared mo...
291
292
293
294
295
296
297
  		return do_refcount_check(mnt, refcnt);
  
  	/*
  	 * quickly check if the current mount can be unmounted.
  	 * If not, we don't have to go checking for all other
  	 * mounts
  	 */
6b41d536f   Al Viro   vfs: take mnt_chi...
298
  	if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt))
a05964f39   Ram Pai   [PATCH] shared mo...
299
  		return 1;
c937135d9   Al Viro   vfs: spread struc...
300
301
  	for (m = propagation_next(parent, parent); m;
  	     		m = propagation_next(m, parent)) {
474279dc0   Al Viro   split __lookup_mn...
302
  		child = __lookup_mnt_last(&m->mnt, mnt->mnt_mountpoint);
6b41d536f   Al Viro   vfs: take mnt_chi...
303
  		if (child && list_empty(&child->mnt_mounts) &&
1ab597386   Al Viro   vfs: spread struc...
304
  		    (ret = do_refcount_check(child, 1)))
a05964f39   Ram Pai   [PATCH] shared mo...
305
306
307
308
309
310
311
312
313
  			break;
  	}
  	return ret;
  }
  
  /*
   * NOTE: unmounting 'mnt' naturally propagates to all other mounts its
   * parent propagates to.
   */
61ef47b1e   Al Viro   vfs: spread struc...
314
  static void __propagate_umount(struct mount *mnt)
a05964f39   Ram Pai   [PATCH] shared mo...
315
  {
0714a5338   Al Viro   vfs: now it can b...
316
  	struct mount *parent = mnt->mnt_parent;
c937135d9   Al Viro   vfs: spread struc...
317
  	struct mount *m;
a05964f39   Ram Pai   [PATCH] shared mo...
318

0714a5338   Al Viro   vfs: now it can b...
319
  	BUG_ON(parent == mnt);
a05964f39   Ram Pai   [PATCH] shared mo...
320

c937135d9   Al Viro   vfs: spread struc...
321
322
  	for (m = propagation_next(parent, parent); m;
  			m = propagation_next(m, parent)) {
a05964f39   Ram Pai   [PATCH] shared mo...
323

474279dc0   Al Viro   split __lookup_mn...
324
325
  		struct mount *child = __lookup_mnt_last(&m->mnt,
  						mnt->mnt_mountpoint);
a05964f39   Ram Pai   [PATCH] shared mo...
326
327
328
329
  		/*
  		 * umount the child only if the child has no
  		 * other children
  		 */
6b41d536f   Al Viro   vfs: take mnt_chi...
330
  		if (child && list_empty(&child->mnt_mounts))
1b8e5564b   Al Viro   vfs: the first sp...
331
  			list_move_tail(&child->mnt_hash, &mnt->mnt_hash);
a05964f39   Ram Pai   [PATCH] shared mo...
332
333
334
335
336
337
338
  	}
  }
  
  /*
   * collect all mounts that receive propagation from the mount in @list,
   * and return these additional mounts in the same list.
   * @list: the list of mounts to be unmounted.
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
339
340
   *
   * vfsmount lock must be held for write
a05964f39   Ram Pai   [PATCH] shared mo...
341
342
343
   */
  int propagate_umount(struct list_head *list)
  {
61ef47b1e   Al Viro   vfs: spread struc...
344
  	struct mount *mnt;
a05964f39   Ram Pai   [PATCH] shared mo...
345

1b8e5564b   Al Viro   vfs: the first sp...
346
  	list_for_each_entry(mnt, list, mnt_hash)
a05964f39   Ram Pai   [PATCH] shared mo...
347
348
349
  		__propagate_umount(mnt);
  	return 0;
  }