aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorDipankar Sarma <dipankar@in.ibm.com>2005-09-09 16:04:10 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 16:57:55 -0400
commitbadf16621c1f9d1ac753be056fce11b43d6e0be5 (patch)
tree3fdf833fdf2e3d3a439090743539680449ec3428 /fs/fcntl.c
parentc0dfb2905126e9e94edebbce8d3e05001301f52d (diff)
[PATCH] files: break up files struct
In order for the RCU to work, the file table array, sets and their sizes must be updated atomically. Instead of ensuring this through too many memory barriers, we put the arrays and their sizes in a separate structure. This patch takes the first step of putting the file table elements in a separate structure fdtable that is embedded withing files_struct. It also changes all the users to refer to the file table using files_fdtable() macro. Subsequent applciation of RCU becomes easier after this. Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com> Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 6fbc9d8fcc36..bfecc6238083 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -24,20 +24,24 @@
24void fastcall set_close_on_exec(unsigned int fd, int flag) 24void fastcall set_close_on_exec(unsigned int fd, int flag)
25{ 25{
26 struct files_struct *files = current->files; 26 struct files_struct *files = current->files;
27 struct fdtable *fdt;
27 spin_lock(&files->file_lock); 28 spin_lock(&files->file_lock);
29 fdt = files_fdtable(files);
28 if (flag) 30 if (flag)
29 FD_SET(fd, files->close_on_exec); 31 FD_SET(fd, fdt->close_on_exec);
30 else 32 else
31 FD_CLR(fd, files->close_on_exec); 33 FD_CLR(fd, fdt->close_on_exec);
32 spin_unlock(&files->file_lock); 34 spin_unlock(&files->file_lock);
33} 35}
34 36
35static inline int get_close_on_exec(unsigned int fd) 37static inline int get_close_on_exec(unsigned int fd)
36{ 38{
37 struct files_struct *files = current->files; 39 struct files_struct *files = current->files;
40 struct fdtable *fdt;
38 int res; 41 int res;
39 spin_lock(&files->file_lock); 42 spin_lock(&files->file_lock);
40 res = FD_ISSET(fd, files->close_on_exec); 43 fdt = files_fdtable(files);
44 res = FD_ISSET(fd, fdt->close_on_exec);
41 spin_unlock(&files->file_lock); 45 spin_unlock(&files->file_lock);
42 return res; 46 return res;
43} 47}
@@ -54,24 +58,26 @@ static int locate_fd(struct files_struct *files,
54 unsigned int newfd; 58 unsigned int newfd;
55 unsigned int start; 59 unsigned int start;
56 int error; 60 int error;
61 struct fdtable *fdt;
57 62
58 error = -EINVAL; 63 error = -EINVAL;
59 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 64 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
60 goto out; 65 goto out;
61 66
67 fdt = files_fdtable(files);
62repeat: 68repeat:
63 /* 69 /*
64 * Someone might have closed fd's in the range 70 * Someone might have closed fd's in the range
65 * orig_start..files->next_fd 71 * orig_start..fdt->next_fd
66 */ 72 */
67 start = orig_start; 73 start = orig_start;
68 if (start < files->next_fd) 74 if (start < fdt->next_fd)
69 start = files->next_fd; 75 start = fdt->next_fd;
70 76
71 newfd = start; 77 newfd = start;
72 if (start < files->max_fdset) { 78 if (start < fdt->max_fdset) {
73 newfd = find_next_zero_bit(files->open_fds->fds_bits, 79 newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
74 files->max_fdset, start); 80 fdt->max_fdset, start);
75 } 81 }
76 82
77 error = -EMFILE; 83 error = -EMFILE;
@@ -89,8 +95,8 @@ repeat:
89 if (error) 95 if (error)
90 goto repeat; 96 goto repeat;
91 97
92 if (start <= files->next_fd) 98 if (start <= fdt->next_fd)
93 files->next_fd = newfd + 1; 99 fdt->next_fd = newfd + 1;
94 100
95 error = newfd; 101 error = newfd;
96 102
@@ -101,13 +107,16 @@ out:
101static int dupfd(struct file *file, unsigned int start) 107static int dupfd(struct file *file, unsigned int start)
102{ 108{
103 struct files_struct * files = current->files; 109 struct files_struct * files = current->files;
110 struct fdtable *fdt;
104 int fd; 111 int fd;
105 112
106 spin_lock(&files->file_lock); 113 spin_lock(&files->file_lock);
107 fd = locate_fd(files, file, start); 114 fd = locate_fd(files, file, start);
108 if (fd >= 0) { 115 if (fd >= 0) {
109 FD_SET(fd, files->open_fds); 116 /* locate_fd() may have expanded fdtable, load the ptr */
110 FD_CLR(fd, files->close_on_exec); 117 fdt = files_fdtable(files);
118 FD_SET(fd, fdt->open_fds);
119 FD_CLR(fd, fdt->close_on_exec);
111 spin_unlock(&files->file_lock); 120 spin_unlock(&files->file_lock);
112 fd_install(fd, file); 121 fd_install(fd, file);
113 } else { 122 } else {
@@ -123,6 +132,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
123 int err = -EBADF; 132 int err = -EBADF;
124 struct file * file, *tofree; 133 struct file * file, *tofree;
125 struct files_struct * files = current->files; 134 struct files_struct * files = current->files;
135 struct fdtable *fdt;
126 136
127 spin_lock(&files->file_lock); 137 spin_lock(&files->file_lock);
128 if (!(file = fcheck(oldfd))) 138 if (!(file = fcheck(oldfd)))
@@ -148,13 +158,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
148 158
149 /* Yes. It's a race. In user space. Nothing sane to do */ 159 /* Yes. It's a race. In user space. Nothing sane to do */
150 err = -EBUSY; 160 err = -EBUSY;
151 tofree = files->fd[newfd]; 161 fdt = files_fdtable(files);
152 if (!tofree && FD_ISSET(newfd, files->open_fds)) 162 tofree = fdt->fd[newfd];
163 if (!tofree && FD_ISSET(newfd, fdt->open_fds))
153 goto out_fput; 164 goto out_fput;
154 165
155 files->fd[newfd] = file; 166 fdt->fd[newfd] = file;
156 FD_SET(newfd, files->open_fds); 167 FD_SET(newfd, fdt->open_fds);
157 FD_CLR(newfd, files->close_on_exec); 168 FD_CLR(newfd, fdt->close_on_exec);
158 spin_unlock(&files->file_lock); 169 spin_unlock(&files->file_lock);
159 170
160 if (tofree) 171 if (tofree)