aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/file_table.c')
-rw-r--r--fs/file_table.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index cbeec70ee31..bfab973c6c5 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -279,11 +279,10 @@ struct file *fget(unsigned int fd)
279 rcu_read_lock(); 279 rcu_read_lock();
280 file = fcheck_files(files, fd); 280 file = fcheck_files(files, fd);
281 if (file) { 281 if (file) {
282 if (!atomic_long_inc_not_zero(&file->f_count)) { 282 /* File object ref couldn't be taken */
283 /* File object ref couldn't be taken */ 283 if (file->f_mode & FMODE_PATH ||
284 rcu_read_unlock(); 284 !atomic_long_inc_not_zero(&file->f_count))
285 return NULL; 285 file = NULL;
286 }
287 } 286 }
288 rcu_read_unlock(); 287 rcu_read_unlock();
289 288
@@ -292,6 +291,25 @@ struct file *fget(unsigned int fd)
292 291
293EXPORT_SYMBOL(fget); 292EXPORT_SYMBOL(fget);
294 293
294struct file *fget_raw(unsigned int fd)
295{
296 struct file *file;
297 struct files_struct *files = current->files;
298
299 rcu_read_lock();
300 file = fcheck_files(files, fd);
301 if (file) {
302 /* File object ref couldn't be taken */
303 if (!atomic_long_inc_not_zero(&file->f_count))
304 file = NULL;
305 }
306 rcu_read_unlock();
307
308 return file;
309}
310
311EXPORT_SYMBOL(fget_raw);
312
295/* 313/*
296 * Lightweight file lookup - no refcnt increment if fd table isn't shared. 314 * Lightweight file lookup - no refcnt increment if fd table isn't shared.
297 * 315 *
@@ -316,6 +334,33 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
316 *fput_needed = 0; 334 *fput_needed = 0;
317 if (atomic_read(&files->count) == 1) { 335 if (atomic_read(&files->count) == 1) {
318 file = fcheck_files(files, fd); 336 file = fcheck_files(files, fd);
337 if (file && (file->f_mode & FMODE_PATH))
338 file = NULL;
339 } else {
340 rcu_read_lock();
341 file = fcheck_files(files, fd);
342 if (file) {
343 if (!(file->f_mode & FMODE_PATH) &&
344 atomic_long_inc_not_zero(&file->f_count))
345 *fput_needed = 1;
346 else
347 /* Didn't get the reference, someone's freed */
348 file = NULL;
349 }
350 rcu_read_unlock();
351 }
352
353 return file;
354}
355
356struct file *fget_raw_light(unsigned int fd, int *fput_needed)
357{
358 struct file *file;
359 struct files_struct *files = current->files;
360
361 *fput_needed = 0;
362 if (atomic_read(&files->count) == 1) {
363 file = fcheck_files(files, fd);
319 } else { 364 } else {
320 rcu_read_lock(); 365 rcu_read_lock();
321 file = fcheck_files(files, fd); 366 file = fcheck_files(files, fd);