diff options
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 61 |
1 files changed, 29 insertions, 32 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index d122074c45e1..0d6831a40565 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -287,10 +287,8 @@ out: | |||
287 | * | 287 | * |
288 | * Returns: errno | 288 | * Returns: errno |
289 | */ | 289 | */ |
290 | |||
291 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff) | 290 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff) |
292 | { | 291 | { |
293 | struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info; | ||
294 | struct buffer_head *dibh; | 292 | struct buffer_head *dibh; |
295 | u32 nlink; | 293 | u32 nlink; |
296 | int error; | 294 | int error; |
@@ -315,42 +313,34 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) | |||
315 | else | 313 | else |
316 | drop_nlink(&ip->i_inode); | 314 | drop_nlink(&ip->i_inode); |
317 | 315 | ||
318 | ip->i_inode.i_ctime.tv_sec = get_seconds(); | 316 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; |
319 | 317 | ||
320 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 318 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
321 | gfs2_dinode_out(ip, dibh->b_data); | 319 | gfs2_dinode_out(ip, dibh->b_data); |
322 | brelse(dibh); | 320 | brelse(dibh); |
323 | mark_inode_dirty(&ip->i_inode); | 321 | mark_inode_dirty(&ip->i_inode); |
324 | 322 | ||
325 | if (ip->i_inode.i_nlink == 0) { | 323 | if (ip->i_inode.i_nlink == 0) |
326 | struct gfs2_rgrpd *rgd; | ||
327 | struct gfs2_holder ri_gh, rg_gh; | ||
328 | |||
329 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
330 | if (error) | ||
331 | goto out; | ||
332 | error = -EIO; | ||
333 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); | ||
334 | if (!rgd) | ||
335 | goto out_norgrp; | ||
336 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh); | ||
337 | if (error) | ||
338 | goto out_norgrp; | ||
339 | |||
340 | gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ | 324 | gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ |
341 | gfs2_glock_dq_uninit(&rg_gh); | 325 | |
342 | out_norgrp: | ||
343 | gfs2_glock_dq_uninit(&ri_gh); | ||
344 | } | ||
345 | out: | ||
346 | return error; | 326 | return error; |
347 | } | 327 | } |
348 | 328 | ||
349 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) | 329 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) |
350 | { | 330 | { |
351 | struct qstr qstr; | 331 | struct qstr qstr; |
332 | struct inode *inode; | ||
352 | gfs2_str2qstr(&qstr, name); | 333 | gfs2_str2qstr(&qstr, name); |
353 | return gfs2_lookupi(dip, &qstr, 1, NULL); | 334 | inode = gfs2_lookupi(dip, &qstr, 1, NULL); |
335 | /* gfs2_lookupi has inconsistent callers: vfs | ||
336 | * related routines expect NULL for no entry found, | ||
337 | * gfs2_lookup_simple callers expect ENOENT | ||
338 | * and do not check for NULL. | ||
339 | */ | ||
340 | if (inode == NULL) | ||
341 | return ERR_PTR(-ENOENT); | ||
342 | else | ||
343 | return inode; | ||
354 | } | 344 | } |
355 | 345 | ||
356 | 346 | ||
@@ -361,8 +351,10 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) | |||
361 | * @is_root: If 1, ignore the caller's permissions | 351 | * @is_root: If 1, ignore the caller's permissions |
362 | * @i_gh: An uninitialized holder for the new inode glock | 352 | * @i_gh: An uninitialized holder for the new inode glock |
363 | * | 353 | * |
364 | * There will always be a vnode (Linux VFS inode) for the d_gh inode unless | 354 | * This can be called via the VFS filldir function when NFS is doing |
365 | * @is_root is true. | 355 | * a readdirplus and the inode which its intending to stat isn't |
356 | * already in cache. In this case we must not take the directory glock | ||
357 | * again, since the readdir call will have already taken that lock. | ||
366 | * | 358 | * |
367 | * Returns: errno | 359 | * Returns: errno |
368 | */ | 360 | */ |
@@ -375,8 +367,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
375 | struct gfs2_holder d_gh; | 367 | struct gfs2_holder d_gh; |
376 | struct gfs2_inum_host inum; | 368 | struct gfs2_inum_host inum; |
377 | unsigned int type; | 369 | unsigned int type; |
378 | int error = 0; | 370 | int error; |
379 | struct inode *inode = NULL; | 371 | struct inode *inode = NULL; |
372 | int unlock = 0; | ||
380 | 373 | ||
381 | if (!name->len || name->len > GFS2_FNAMESIZE) | 374 | if (!name->len || name->len > GFS2_FNAMESIZE) |
382 | return ERR_PTR(-ENAMETOOLONG); | 375 | return ERR_PTR(-ENAMETOOLONG); |
@@ -388,9 +381,12 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
388 | return dir; | 381 | return dir; |
389 | } | 382 | } |
390 | 383 | ||
391 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | 384 | if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) { |
392 | if (error) | 385 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
393 | return ERR_PTR(error); | 386 | if (error) |
387 | return ERR_PTR(error); | ||
388 | unlock = 1; | ||
389 | } | ||
394 | 390 | ||
395 | if (!is_root) { | 391 | if (!is_root) { |
396 | error = permission(dir, MAY_EXEC, NULL); | 392 | error = permission(dir, MAY_EXEC, NULL); |
@@ -405,10 +401,11 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
405 | inode = gfs2_inode_lookup(sb, &inum, type); | 401 | inode = gfs2_inode_lookup(sb, &inum, type); |
406 | 402 | ||
407 | out: | 403 | out: |
408 | gfs2_glock_dq_uninit(&d_gh); | 404 | if (unlock) |
405 | gfs2_glock_dq_uninit(&d_gh); | ||
409 | if (error == -ENOENT) | 406 | if (error == -ENOENT) |
410 | return NULL; | 407 | return NULL; |
411 | return inode; | 408 | return inode ? inode : ERR_PTR(error); |
412 | } | 409 | } |
413 | 410 | ||
414 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) | 411 | static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) |