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.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index eb36b6b17e26..3c16e1ca163e 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -276,11 +276,10 @@ struct file *fget(unsigned int fd)
276 rcu_read_lock(); 276 rcu_read_lock();
277 file = fcheck_files(files, fd); 277 file = fcheck_files(files, fd);
278 if (file) { 278 if (file) {
279 if (!atomic_long_inc_not_zero(&file->f_count)) { 279 /* File object ref couldn't be taken */
280 /* File object ref couldn't be taken */ 280 if (file->f_mode & FMODE_PATH ||
281 rcu_read_unlock(); 281 !atomic_long_inc_not_zero(&file->f_count))
282 return NULL; 282 file = NULL;
283 }
284 } 283 }
285 rcu_read_unlock(); 284 rcu_read_unlock();
286 285
@@ -289,6 +288,23 @@ struct file *fget(unsigned int fd)
289 288
290EXPORT_SYMBOL(fget); 289EXPORT_SYMBOL(fget);
291 290
291struct file *fget_raw(unsigned int fd)
292{
293 struct file *file;
294 struct files_struct *files = current->files;
295
296 rcu_read_lock();
297 file = fcheck_files(files, fd);
298 if (file) {
299 /* File object ref couldn't be taken */
300 if (!atomic_long_inc_not_zero(&file->f_count))
301 file = NULL;
302 }
303 rcu_read_unlock();
304
305 return file;
306}
307
292/* 308/*
293 * Lightweight file lookup - no refcnt increment if fd table isn't shared. 309 * Lightweight file lookup - no refcnt increment if fd table isn't shared.
294 * 310 *
@@ -313,6 +329,33 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
313 *fput_needed = 0; 329 *fput_needed = 0;
314 if (atomic_read(&files->count) == 1) { 330 if (atomic_read(&files->count) == 1) {
315 file = fcheck_files(files, fd); 331 file = fcheck_files(files, fd);
332 if (file && (file->f_mode & FMODE_PATH))
333 file = NULL;
334 } else {
335 rcu_read_lock();
336 file = fcheck_files(files, fd);
337 if (file) {
338 if (!(file->f_mode & FMODE_PATH) &&
339 atomic_long_inc_not_zero(&file->f_count))
340 *fput_needed = 1;
341 else
342 /* Didn't get the reference, someone's freed */
343 file = NULL;
344 }
345 rcu_read_unlock();
346 }
347
348 return file;
349}
350
351struct file *fget_raw_light(unsigned int fd, int *fput_needed)
352{
353 struct file *file;
354 struct files_struct *files = current->files;
355
356 *fput_needed = 0;
357 if (atomic_read(&files->count) == 1) {
358 file = fcheck_files(files, fd);
316 } else { 359 } else {
317 rcu_read_lock(); 360 rcu_read_lock();
318 file = fcheck_files(files, fd); 361 file = fcheck_files(files, fd);