diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:54:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:54:14 -0400 |
commit | 1d77062b1402aef5b26e1d3776991126e8026bde (patch) | |
tree | 96e4da18878f5fb2ae50b260e194b78803d4c7a9 /fs/namespace.c | |
parent | 25581ad107be24b89d805da51a03d616f8f3d1be (diff) | |
parent | 76a9f26c9e40e9c0ed5dc8f0cedd74e733f0088d (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (51 commits)
nfs: remove nfs_put_link()
nfs-build-fix-99
git-nfs-build-fixes
Merge branch 'odirect'
NFS: alloc nfs_read/write_data as direct I/O is scheduled
NFS: Eliminate nfs_get_user_pages()
NFS: refactor nfs_direct_free_user_pages
NFS: remove user_addr, user_count, and pos from nfs_direct_req
NFS: "open code" the NFS direct write rescheduler
NFS: Separate functions for counting outstanding NFS direct I/Os
NLM: Fix reclaim races
NLM: sem to mutex conversion
locks.c: add the fl_owner to nlm_compare_locks
NFS: Display the chosen RPCSEC_GSS security flavour in /proc/mounts
NFS: Split fs/nfs/inode.c
NFS: Fix typo in nfs_do_clone_mount()
NFS: Fix compile errors introduced by referrals patches
NFSv4: Ensure that referral mounts bind to a reserved port
NFSv4: A root pathname is sent as a zero component4
NFSv4: Follow a referral
...
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 128 |
1 files changed, 101 insertions, 27 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index c13072a5f1ee..866430bb024d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -585,8 +585,8 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
585 | */ | 585 | */ |
586 | 586 | ||
587 | lock_kernel(); | 587 | lock_kernel(); |
588 | if ((flags & MNT_FORCE) && sb->s_op->umount_begin) | 588 | if (sb->s_op->umount_begin) |
589 | sb->s_op->umount_begin(sb); | 589 | sb->s_op->umount_begin(mnt, flags); |
590 | unlock_kernel(); | 590 | unlock_kernel(); |
591 | 591 | ||
592 | /* | 592 | /* |
@@ -1172,13 +1172,46 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, | |||
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | /* | 1174 | /* |
1175 | * go through the vfsmounts we've just consigned to the graveyard to | ||
1176 | * - check that they're still dead | ||
1177 | * - delete the vfsmount from the appropriate namespace under lock | ||
1178 | * - dispose of the corpse | ||
1179 | */ | ||
1180 | static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts) | ||
1181 | { | ||
1182 | struct namespace *namespace; | ||
1183 | struct vfsmount *mnt; | ||
1184 | |||
1185 | while (!list_empty(graveyard)) { | ||
1186 | LIST_HEAD(umounts); | ||
1187 | mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire); | ||
1188 | list_del_init(&mnt->mnt_expire); | ||
1189 | |||
1190 | /* don't do anything if the namespace is dead - all the | ||
1191 | * vfsmounts from it are going away anyway */ | ||
1192 | namespace = mnt->mnt_namespace; | ||
1193 | if (!namespace || !namespace->root) | ||
1194 | continue; | ||
1195 | get_namespace(namespace); | ||
1196 | |||
1197 | spin_unlock(&vfsmount_lock); | ||
1198 | down_write(&namespace_sem); | ||
1199 | expire_mount(mnt, mounts, &umounts); | ||
1200 | up_write(&namespace_sem); | ||
1201 | release_mounts(&umounts); | ||
1202 | mntput(mnt); | ||
1203 | put_namespace(namespace); | ||
1204 | spin_lock(&vfsmount_lock); | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1175 | * process a list of expirable mountpoints with the intent of discarding any | 1209 | * process a list of expirable mountpoints with the intent of discarding any |
1176 | * mountpoints that aren't in use and haven't been touched since last we came | 1210 | * mountpoints that aren't in use and haven't been touched since last we came |
1177 | * here | 1211 | * here |
1178 | */ | 1212 | */ |
1179 | void mark_mounts_for_expiry(struct list_head *mounts) | 1213 | void mark_mounts_for_expiry(struct list_head *mounts) |
1180 | { | 1214 | { |
1181 | struct namespace *namespace; | ||
1182 | struct vfsmount *mnt, *next; | 1215 | struct vfsmount *mnt, *next; |
1183 | LIST_HEAD(graveyard); | 1216 | LIST_HEAD(graveyard); |
1184 | 1217 | ||
@@ -1202,38 +1235,79 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
1202 | list_move(&mnt->mnt_expire, &graveyard); | 1235 | list_move(&mnt->mnt_expire, &graveyard); |
1203 | } | 1236 | } |
1204 | 1237 | ||
1205 | /* | 1238 | expire_mount_list(&graveyard, mounts); |
1206 | * go through the vfsmounts we've just consigned to the graveyard to | ||
1207 | * - check that they're still dead | ||
1208 | * - delete the vfsmount from the appropriate namespace under lock | ||
1209 | * - dispose of the corpse | ||
1210 | */ | ||
1211 | while (!list_empty(&graveyard)) { | ||
1212 | LIST_HEAD(umounts); | ||
1213 | mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire); | ||
1214 | list_del_init(&mnt->mnt_expire); | ||
1215 | 1239 | ||
1216 | /* don't do anything if the namespace is dead - all the | 1240 | spin_unlock(&vfsmount_lock); |
1217 | * vfsmounts from it are going away anyway */ | 1241 | } |
1218 | namespace = mnt->mnt_namespace; | 1242 | |
1219 | if (!namespace || !namespace->root) | 1243 | EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); |
1244 | |||
1245 | /* | ||
1246 | * Ripoff of 'select_parent()' | ||
1247 | * | ||
1248 | * search the list of submounts for a given mountpoint, and move any | ||
1249 | * shrinkable submounts to the 'graveyard' list. | ||
1250 | */ | ||
1251 | static int select_submounts(struct vfsmount *parent, struct list_head *graveyard) | ||
1252 | { | ||
1253 | struct vfsmount *this_parent = parent; | ||
1254 | struct list_head *next; | ||
1255 | int found = 0; | ||
1256 | |||
1257 | repeat: | ||
1258 | next = this_parent->mnt_mounts.next; | ||
1259 | resume: | ||
1260 | while (next != &this_parent->mnt_mounts) { | ||
1261 | struct list_head *tmp = next; | ||
1262 | struct vfsmount *mnt = list_entry(tmp, struct vfsmount, mnt_child); | ||
1263 | |||
1264 | next = tmp->next; | ||
1265 | if (!(mnt->mnt_flags & MNT_SHRINKABLE)) | ||
1220 | continue; | 1266 | continue; |
1221 | get_namespace(namespace); | 1267 | /* |
1268 | * Descend a level if the d_mounts list is non-empty. | ||
1269 | */ | ||
1270 | if (!list_empty(&mnt->mnt_mounts)) { | ||
1271 | this_parent = mnt; | ||
1272 | goto repeat; | ||
1273 | } | ||
1222 | 1274 | ||
1223 | spin_unlock(&vfsmount_lock); | 1275 | if (!propagate_mount_busy(mnt, 1)) { |
1224 | down_write(&namespace_sem); | 1276 | mntget(mnt); |
1225 | expire_mount(mnt, mounts, &umounts); | 1277 | list_move_tail(&mnt->mnt_expire, graveyard); |
1226 | up_write(&namespace_sem); | 1278 | found++; |
1227 | release_mounts(&umounts); | 1279 | } |
1228 | mntput(mnt); | ||
1229 | put_namespace(namespace); | ||
1230 | spin_lock(&vfsmount_lock); | ||
1231 | } | 1280 | } |
1281 | /* | ||
1282 | * All done at this level ... ascend and resume the search | ||
1283 | */ | ||
1284 | if (this_parent != parent) { | ||
1285 | next = this_parent->mnt_child.next; | ||
1286 | this_parent = this_parent->mnt_parent; | ||
1287 | goto resume; | ||
1288 | } | ||
1289 | return found; | ||
1290 | } | ||
1291 | |||
1292 | /* | ||
1293 | * process a list of expirable mountpoints with the intent of discarding any | ||
1294 | * submounts of a specific parent mountpoint | ||
1295 | */ | ||
1296 | void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts) | ||
1297 | { | ||
1298 | LIST_HEAD(graveyard); | ||
1299 | int found; | ||
1300 | |||
1301 | spin_lock(&vfsmount_lock); | ||
1302 | |||
1303 | /* extract submounts of 'mountpoint' from the expiration list */ | ||
1304 | while ((found = select_submounts(mountpoint, &graveyard)) != 0) | ||
1305 | expire_mount_list(&graveyard, mounts); | ||
1232 | 1306 | ||
1233 | spin_unlock(&vfsmount_lock); | 1307 | spin_unlock(&vfsmount_lock); |
1234 | } | 1308 | } |
1235 | 1309 | ||
1236 | EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); | 1310 | EXPORT_SYMBOL_GPL(shrink_submounts); |
1237 | 1311 | ||
1238 | /* | 1312 | /* |
1239 | * Some copy_from_user() implementations do not return the exact number of | 1313 | * Some copy_from_user() implementations do not return the exact number of |