diff options
Diffstat (limited to 'fs/adfs/dir.c')
-rw-r--r-- | fs/adfs/dir.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index ff9c921be31c..5e5d344bae7c 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -64,12 +64,8 @@ int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src, return 0; } -void adfs_dir_relse(struct adfs_dir *dir) +static void __adfs_dir_cleanup(struct adfs_dir *dir) { - unsigned int i; - - for (i = 0; i < dir->nr_buffers; i++) - brelse(dir->bhs[i]); dir->nr_buffers = 0; if (dir->bhs != dir->bh) @@ -78,6 +74,26 @@ void adfs_dir_relse(struct adfs_dir *dir) dir->sb = NULL; } +void adfs_dir_relse(struct adfs_dir *dir) +{ + unsigned int i; + + for (i = 0; i < dir->nr_buffers; i++) + brelse(dir->bhs[i]); + + __adfs_dir_cleanup(dir); +} + +static void adfs_dir_forget(struct adfs_dir *dir) +{ + unsigned int i; + + for (i = 0; i < dir->nr_buffers; i++) + bforget(dir->bhs[i]); + + __adfs_dir_cleanup(dir); +} + int adfs_dir_read_buffers(struct super_block *sb, u32 indaddr, unsigned int size, struct adfs_dir *dir) { @@ -288,20 +304,28 @@ adfs_dir_update(struct super_block *sb, struct object_info *obj, int wait) goto unlock; ret = ops->update(&dir, obj); + if (ret) + goto forget; up_write(&adfs_dir_rwsem); - if (ret == 0) - adfs_dir_mark_dirty(&dir); + adfs_dir_mark_dirty(&dir); - if (wait) { - int err = adfs_dir_sync(&dir); - if (!ret) - ret = err; - } + if (wait) + ret = adfs_dir_sync(&dir); adfs_dir_relse(&dir); return ret; + /* + * If the updated failed because the entry wasn't found, we can + * just release the buffers. If it was any other error, forget + * the dirtied buffers so they aren't written back to the media. + */ +forget: + if (ret == -ENOENT) + adfs_dir_relse(&dir); + else + adfs_dir_forget(&dir); unlock: up_write(&adfs_dir_rwsem); #endif |