]> git.karo-electronics.de Git - linux-beck.git/blobdiff - fs/ubifs/file.c
inotify: fix IN_ONESHOT unmount event watcher
[linux-beck.git] / fs / ubifs / file.c
index 0c5c27d63f6e3d38eac9949e39990bb23132fdb1..2624411d9758d11023c938418f8a6a7938066ff5 100644 (file)
@@ -811,15 +811,15 @@ static int ubifs_bulk_read(struct page *page)
        struct ubifs_inode *ui = ubifs_inode(inode);
        pgoff_t index = page->index, last_page_read = ui->last_page_read;
        struct bu_info *bu;
-       int err = 0;
+       int err = 0, allocated = 0;
 
        ui->last_page_read = index;
        if (!c->bulk_read)
                return 0;
 
        /*
-        * Bulk-read is protected by ui_mutex, but it is an optimization, so
-        * don't bother if we cannot lock the mutex.
+        * Bulk-read is protected by @ui->ui_mutex, but it is an optimization,
+        * so don't bother if we cannot lock the mutex.
         */
        if (!mutex_trylock(&ui->ui_mutex))
                return 0;
@@ -840,17 +840,30 @@ static int ubifs_bulk_read(struct page *page)
                ui->bulk_read = 1;
        }
 
-       bu = kmalloc(sizeof(struct bu_info), GFP_NOFS | __GFP_NOWARN);
-       if (!bu)
-               return 0;
+       /*
+        * If possible, try to use pre-allocated bulk-read information, which
+        * is protected by @c->bu_mutex.
+        */
+       if (mutex_trylock(&c->bu_mutex))
+               bu = &c->bu;
+       else {
+               bu = kmalloc(sizeof(struct bu_info), GFP_NOFS | __GFP_NOWARN);
+               if (!bu)
+                       goto out_unlock;
+
+               bu->buf = NULL;
+               allocated = 1;
+       }
 
-       bu->buf = NULL;
        bu->buf_len = c->max_bu_buf_len;
        data_key_init(c, &bu->key, inode->i_ino,
                      page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT);
-
        err = ubifs_do_bulk_read(c, bu, page);
-       kfree(bu);
+
+       if (!allocated)
+               mutex_unlock(&c->bu_mutex);
+       else
+               kfree(bu);
 
 out_unlock:
        mutex_unlock(&ui->ui_mutex);