At one point I was considering using s_files, the list of files associated with a single superblock, to find open state in need of reclaiming after a server reboot. So I wanted to understand how the s_files list is used, and how to traverse it safely. A file is added to the list of open files *before* the file->open method is called; see dentry_open: file_move(f, &inode->i_sb->s_files); if (f->f_op && f->f_op->open) { error = f->f_op->open(inode,f); where file_move installs file in the file list, from file_table.c: void file_move(struct file *file, struct list_head *list) { if (!list) return; file_list_lock(); list_move(&file->f_list, list); file_list_unlock(); } and file_list_{un}lock is just spin_{un}lock(&files_lock). where sequence of calls is something like: sys_open: filp_open: open_namei: path_lookup's vfs_create if necessary dentry_open Examples of other places s_files is used: add_dquot_ref (in quota code): file_list_lock() for each file in sb->s_files if need to do something with this file, file_list_unlock(), do it, then start everything over. file_list_unlock() fs_may_remount_ro: file_list_lock() for each file in sb->s_files if file is to be deleted, of if file's open for write, unlock and return 0 file_list_unlock(), return true. Similarly, for per-filesystem and global lists of superblocks, how is iterating over them handled? One example is sync_inodes, which does a while(get_super_to_sync()), where get_super_to_sync: spin_lock(&sb_lock) loop over superblock list: if we find one with s_syncing false, set s_syncing = 1 sb->s_count++; spin_unlock(&sb_lock) down_read(&sb->s_umount) if !sb->s_root: drop_super(sb) goto restart return sb; spin_unlock(&sb_lock); return NULL; so basically this is the same as the add_dquot_ref above; we have a flag to mark sb's we've already seen, and each time through the list we grab the spinlock again and start over from the beginning.