aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file.c
diff options
context:
space:
mode:
authorVadim Lobanov <vlobanov@speakeasy.net>2006-12-10 05:21:17 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:57:22 -0500
commit4fd45812cbe875a620c86a096a5d46c742694b7e (patch)
tree8d2c99caa718da6cda87229076adf708494ff251 /fs/file.c
parentbbea9f69668a3d0cf9feba15a724cd02896f8675 (diff)
[PATCH] fdtable: Remove the free_files field
An fdtable can either be embedded inside a files_struct or standalone (after being expanded). When an fdtable is being discarded after all RCU references to it have expired, we must either free it directly, in the standalone case, or free the files_struct it is contained within, in the embedded case. Currently the free_files field controls this behavior, but we can get rid of it entirely, as all the necessary information is already recorded. We can distinguish embedded and standalone fdtables using max_fds, and if it is embedded we can divine the relevant files_struct using container_of(). Signed-off-by: Vadim Lobanov <vlobanov@speakeasy.net> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Dipankar Sarma <dipankar@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c27
1 files changed, 8 insertions, 19 deletions
diff --git a/fs/file.c b/fs/file.c
index fb3d2038dc21..17e6a55521e2 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -91,7 +91,7 @@ static void free_fdtable_work(struct work_struct *work)
91 } 91 }
92} 92}
93 93
94static void free_fdtable_rcu(struct rcu_head *rcu) 94void free_fdtable_rcu(struct rcu_head *rcu)
95{ 95{
96 struct fdtable *fdt = container_of(rcu, struct fdtable, rcu); 96 struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
97 int fdset_size, fdarray_size; 97 int fdset_size, fdarray_size;
@@ -101,20 +101,15 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
101 fdset_size = fdt->max_fds / 8; 101 fdset_size = fdt->max_fds / 8;
102 fdarray_size = fdt->max_fds * sizeof(struct file *); 102 fdarray_size = fdt->max_fds * sizeof(struct file *);
103 103
104 if (fdt->free_files) { 104 if (fdt->max_fds <= NR_OPEN_DEFAULT) {
105 /* 105 /*
106 * The this fdtable was embedded in the files structure 106 * This fdtable is embedded in the files structure and that
107 * and the files structure itself was getting destroyed. 107 * structure itself is getting destroyed.
108 * It is now safe to free the files structure.
109 */ 108 */
110 kmem_cache_free(files_cachep, fdt->free_files); 109 kmem_cache_free(files_cachep,
110 container_of(fdt, struct files_struct, fdtab));
111 return; 111 return;
112 } 112 }
113 if (fdt->max_fds <= NR_OPEN_DEFAULT)
114 /*
115 * The fdtable was embedded
116 */
117 return;
118 if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) { 113 if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
119 kfree(fdt->open_fds); 114 kfree(fdt->open_fds);
120 kfree(fdt->close_on_exec); 115 kfree(fdt->close_on_exec);
@@ -132,12 +127,6 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
132 } 127 }
133} 128}
134 129
135void free_fdtable(struct fdtable *fdt)
136{
137 if (fdt->free_files || fdt->max_fds > NR_OPEN_DEFAULT)
138 call_rcu(&fdt->rcu, free_fdtable_rcu);
139}
140
141/* 130/*
142 * Expand the fdset in the files_struct. Called with the files spinlock 131 * Expand the fdset in the files_struct. Called with the files spinlock
143 * held for write. 132 * held for write.
@@ -247,7 +236,6 @@ static struct fdtable *alloc_fdtable(int nr)
247 goto out; 236 goto out;
248 fdt->fd = new_fds; 237 fdt->fd = new_fds;
249 fdt->max_fds = nfds; 238 fdt->max_fds = nfds;
250 fdt->free_files = NULL;
251 return fdt; 239 return fdt;
252out: 240out:
253 free_fdset(new_openset, nfds); 241 free_fdset(new_openset, nfds);
@@ -283,7 +271,8 @@ static int expand_fdtable(struct files_struct *files, int nr)
283 /* Continue as planned */ 271 /* Continue as planned */
284 copy_fdtable(new_fdt, cur_fdt); 272 copy_fdtable(new_fdt, cur_fdt);
285 rcu_assign_pointer(files->fdt, new_fdt); 273 rcu_assign_pointer(files->fdt, new_fdt);
286 free_fdtable(cur_fdt); 274 if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
275 call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
287 } else { 276 } else {
288 /* Somebody else expanded, so undo our attempt */ 277 /* Somebody else expanded, so undo our attempt */
289 __free_fdtable(new_fdt); 278 __free_fdtable(new_fdt);