nfsd: Fix a memory leak in nfsd4_list_rec_dir()
authorKinglong Mee <kinglongmee@gmail.com>
Tue, 7 Jul 2015 02:13:02 +0000 (10:13 +0800)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 20 Jul 2015 18:58:45 +0000 (14:58 -0400)
If lookup_one_len() failed, nfsd should free those memory allocated for fname.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4recover.c

index d88ea7b9a85cbf4557d7689872150d08d33e4e64..591bfbdf0316dd3115e4f36dd369361abe9182a1 100644 (file)
@@ -272,6 +272,7 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
                .ctx.actor = nfsd4_build_namelist,
                .names = LIST_HEAD_INIT(ctx.names)
        };
+       struct name_list *entry, *tmp;
        int status;
 
        status = nfs4_save_creds(&original_cred);
@@ -286,9 +287,8 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
 
        status = iterate_dir(nn->rec_file, &ctx.ctx);
        mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
-       while (!list_empty(&ctx.names)) {
-               struct name_list *entry;
-               entry = list_entry(ctx.names.next, struct name_list, list);
+
+       list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
                if (!status) {
                        struct dentry *dentry;
                        dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
@@ -304,6 +304,12 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
        }
        mutex_unlock(&d_inode(dir)->i_mutex);
        nfs4_reset_creds(original_cred);
+
+       list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
+               dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name);
+               list_del(&entry->list);
+               kfree(entry);
+       }
        return status;
 }