From mboxrd@z Thu Jan 1 00:00:00 1970 From: viro@parcelfarce.linux.theplanet.co.uk Subject: Re: inode->i_op->rename semantics . Date: Fri, 16 May 2003 02:09:29 +0100 Sender: linux-fsdevel-owner@vger.kernel.org Message-ID: <20030516010929.GF10374@parcelfarce.linux.theplanet.co.uk> References: <20030514153314.GZ10374@parcelfarce.linux.theplanet.co.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: linux-fsdevel@vger.kernel.org Return-path: Received: from parcelfarce.linux.theplanet.co.uk ([195.92.249.252]:27051 "EHLO www.linux.org.uk") by vger.kernel.org with ESMTP id S264324AbTEPA4j (ORCPT ); Thu, 15 May 2003 20:56:39 -0400 To: Nir Tzachar Content-Disposition: inline In-Reply-To: List-Id: linux-fsdevel.vger.kernel.org On Thu, May 15, 2003 at 10:46:42AM +0300, Nir Tzachar wrote: > first, thanks for your help ;) > > now, i still haver some problems: > > > Leave association between dentries and inodes alone; VFS will call > > d_move() afterwards and it will do the right thing. > im not messing with dentry<->inode associations . > anyway, i tried to read the d_move() code, but some explanations will be > appreciated. > > > All you need to do in ->rename() is > > a) modify on-disk structures > im doing this. > > > b) update ->i_nlink for inodes that need it. > which inodes need it? wont the vfs update ->i_nlink for them? No. ->i_nlink is the number of (on-disk) directory entries that point to your (on-disk) inodes. VFS has no business touching it - it belongs to filesystem data structures and is responsibility of filesystem code. In other words, ->i_nlink changes should reflect the changes of directory tree: if target exists, we need to decrement its ->i_nlink since target directory entry is not pointing to it anymore. if we are moving a directory, old parent should have ->i_nlink decremented and new one - incremented, since '..' in the child now points to new parent. if target was an empty directory, we should also decrement ->i_nlink on target and target's parent since '.' and '..' in target are goners now. > if i need to update ->i_nlink, should i also iput/iget them?? or will the > vfs do this also?? (im asking, because i didnt see this kind of code > anywhere in the vfs code. ) Updates of ->i_nlink have nothing to do with iput/iget. All right, let's take a look at the way it works. Suppose we rename foo/a to bar/a, both exist and are regular files. We have two dentries (for foo/a and bar/a resp.) and two inodes. ->rename() will update data structures on disk and decrement ->i_nlink for target. Then d_move() is called. Note that at this point dentries still reflect the *old* state - they had not been moved/renamed/etc. yet. d_move() does it. It will * unhash dentry of bar/a * exchange the names and parents between dentries of foo/a and bar/a Now we have the dentry of target unhashed (still with the same inode) and dentry of source successfully renamed. Now we drop our references to both dentries. Since target had been unhashed, it will be freed as soon as the last reference is dropped. Freeing it will drop the reference to its inode (i.e. inode that used to be bar/a). _If_ there was no other links to that inode, iput() will see that it's time to delete it and call filesystem ->delete_inode(). Note that we can't do anything about that sequence of operations. Indeed, if somebody had bar/a opened, we have to keep it alive until it's finally closed. It is detached from bar, no lookups will find it, but we can't free inode yet. IOW, ->rename() itself shouldn't free any inodes - it's left to VFS code. Normally it happens when rename(2) does dput() on dentries it had dealt with, but it can happen later if somebody is also holding them. It might be easier if you had shown your code, actually. Are you sure that you do not leak references to dentries somewhere? That would explain the things - inode removal is triggered by releasing the last reference to dentry and if that never happens...