}
}
-static void free_fdtable_rcu(struct rcu_head *rcu)
+void free_fdtable_rcu(struct rcu_head *rcu)
{
struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
int fdset_size, fdarray_size;
fdset_size = fdt->max_fds / 8;
fdarray_size = fdt->max_fds * sizeof(struct file *);
- if (fdt->free_files) {
+ if (fdt->max_fds <= NR_OPEN_DEFAULT) {
/*
- * The this fdtable was embedded in the files structure
- * and the files structure itself was getting destroyed.
- * It is now safe to free the files structure.
+ * This fdtable is embedded in the files structure and that
+ * structure itself is getting destroyed.
*/
- kmem_cache_free(files_cachep, fdt->free_files);
+ kmem_cache_free(files_cachep,
+ container_of(fdt, struct files_struct, fdtab));
return;
}
- if (fdt->max_fds <= NR_OPEN_DEFAULT)
- /*
- * The fdtable was embedded
- */
- return;
if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
kfree(fdt->open_fds);
kfree(fdt->close_on_exec);
}
}
-void free_fdtable(struct fdtable *fdt)
-{
- if (fdt->free_files || fdt->max_fds > NR_OPEN_DEFAULT)
- call_rcu(&fdt->rcu, free_fdtable_rcu);
-}
-
/*
* Expand the fdset in the files_struct. Called with the files spinlock
* held for write.
goto out;
fdt->fd = new_fds;
fdt->max_fds = nfds;
- fdt->free_files = NULL;
return fdt;
out:
free_fdset(new_openset, nfds);
/* Continue as planned */
copy_fdtable(new_fdt, cur_fdt);
rcu_assign_pointer(files->fdt, new_fdt);
- free_fdtable(cur_fdt);
+ if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
+ call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
} else {
/* Somebody else expanded, so undo our attempt */
__free_fdtable(new_fdt);
fd_set *close_on_exec;
fd_set *open_fds;
struct rcu_head rcu;
- struct files_struct *free_files;
struct fdtable *next;
};
extern void free_fdset(fd_set *, int);
extern int expand_files(struct files_struct *, int nr);
-extern void free_fdtable(struct fdtable *fdt);
+extern void free_fdtable_rcu(struct rcu_head *rcu);
extern void __init files_defer_init(void);
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
* you can free files immediately.
*/
fdt = files_fdtable(files);
- if (fdt == &files->fdtab)
- fdt->free_files = files;
- else
+ if (fdt != &files->fdtab)
kmem_cache_free(files_cachep, files);
- free_fdtable(fdt);
+ call_rcu(&fdt->rcu, free_fdtable_rcu);
}
}