int au_do_open_nondir(struct file *file, int flags) { int err; aufs_bindex_t bindex; struct file *h_file; struct dentry *dentry; struct au_finfo *finfo; FiMustWriteLock(file); err = 0; dentry = file->f_dentry; finfo = au_fi(file); memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); atomic_set(&finfo->fi_mmapped, 0); bindex = au_dbstart(dentry); h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); if (IS_ERR(h_file)) err = PTR_ERR(h_file); else { au_set_fbstart(file, bindex); au_set_h_fptr(file, bindex, h_file); au_update_figen(file); finfo->fi_file = file; au_sphl_add(&finfo->fi_hlist, &au_sbi(dentry->d_sb)->si_files); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ } return err; }
int au_do_open_nondir(struct file *file, int flags) { int err; aufs_bindex_t bindex; struct file *h_file; struct dentry *dentry; struct au_finfo *finfo; FiMustWriteLock(file); err = 0; dentry = file->f_dentry; finfo = au_fi(file); memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); finfo->fi_hvmop = NULL; bindex = au_dbstart(dentry); /* O_TRUNC is processed already */ BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode) && (flags & O_TRUNC)); h_file = au_h_open(dentry, bindex, flags, file); if (IS_ERR(h_file)) err = PTR_ERR(h_file); else { au_set_fbstart(file, bindex); au_set_h_fptr(file, bindex, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ } return err; }
int au_do_open_nondir(struct file *file, int flags) { int err; aufs_bindex_t bindex; struct file *h_file; struct dentry *dentry; struct au_finfo *finfo; FiMustWriteLock(file); dentry = file->f_dentry; err = au_d_alive(dentry); if (unlikely(err)) goto out; finfo = au_fi(file); memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); finfo->fi_hvmop = NULL; bindex = au_dbstart(dentry); h_file = au_h_open(dentry, bindex, flags, file); if (IS_ERR(h_file)) err = PTR_ERR(h_file); else { au_set_fbstart(file, bindex); au_set_h_fptr(file, bindex, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ } out: return err; }
/* * after branch manipulating, refresh the file. */ static int refresh_file(struct file *file, int (*reopen)(struct file *file)) { int err, need_reopen; struct dentry *dentry; aufs_bindex_t bend, bindex; dentry = file->f_dentry; err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1); if (unlikely(err)) goto out; au_do_refresh_file(file); err = 0; need_reopen = 1; if (!au_test_mmapped(file)) err = au_file_refresh_by_inode(file, &need_reopen); if (!err && need_reopen && !d_unhashed(dentry)) err = reopen(file); if (!err) { au_update_figen(file); return 0; /* success */ } /* error, close all lower files */ bend = au_fbend(file); for (bindex = au_fbstart(file); bindex <= bend; bindex++) au_set_h_fptr(file, bindex, NULL); out: return err; }
int au_reopen_nondir(struct file *file) { int err; aufs_bindex_t bstart; struct dentry *dentry; struct file *h_file, *h_file_tmp; dentry = file->f_dentry; AuDebugOn(au_special_file(dentry->d_inode->i_mode)); bstart = au_dbstart(dentry); h_file_tmp = NULL; if (au_fbstart(file) == bstart) { h_file = au_hf_top(file); if (file->f_mode == h_file->f_mode) return 0; /* success */ h_file_tmp = h_file; get_file(h_file_tmp); au_set_h_fptr(file, bstart, NULL); } AuDebugOn(au_fi(file)->fi_hdir); /* * it can happen * file exists on both of rw and ro * open --> dbstart and fbstart are both 0 * prepend a branch as rw, "rw" become ro * remove rw/file * delete the top branch, "rw" becomes rw again * --> dbstart is 1, fbstart is still 0 * write --> fbstart is 0 but dbstart is 1 */ /* AuDebugOn(au_fbstart(file) < bstart); */ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC, file, /*force_wr*/0); err = PTR_ERR(h_file); if (IS_ERR(h_file)) { if (h_file_tmp) { atomic_inc(&au_sbr(dentry->d_sb, bstart)->br_count); au_set_h_fptr(file, bstart, h_file_tmp); h_file_tmp = NULL; } goto out; /* todo: close all? */ } err = 0; au_set_fbstart(file, bstart); au_set_h_fptr(file, bstart, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ out: if (h_file_tmp) fput(h_file_tmp); return err; }
static int do_open_dir(struct file *file, int flags, struct file *h_file) { int err; aufs_bindex_t bindex, btail; struct dentry *dentry, *h_dentry; struct vfsmount *mnt; FiMustWriteLock(file); AuDebugOn(h_file); err = 0; mnt = file->f_path.mnt; dentry = file->f_path.dentry; file->f_version = d_inode(dentry)->i_version; bindex = au_dbtop(dentry); au_set_fbtop(file, bindex); btail = au_dbtaildir(dentry); au_set_fbbot_dir(file, btail); for (; !err && bindex <= btail; bindex++) { h_dentry = au_h_dptr(dentry, bindex); if (!h_dentry) continue; err = vfsub_test_mntns(mnt, h_dentry->d_sb); if (unlikely(err)) break; h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); if (IS_ERR(h_file)) { err = PTR_ERR(h_file); break; } au_set_h_fptr(file, bindex, h_file); } au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ if (!err) return 0; /* success */ /* close all */ for (bindex = au_fbtop(file); bindex <= btail; bindex++) au_set_h_fptr(file, bindex, NULL); au_set_fbtop(file, -1); au_set_fbbot_dir(file, -1); return err; }
static int do_open_dir(struct file *file, int flags) { int err; aufs_bindex_t bindex, btail; struct dentry *dentry, *h_dentry; struct file *h_file; FiMustWriteLock(file); dentry = file->f_dentry; err = au_alive_dir(dentry); if (unlikely(err)) goto out; file->f_version = dentry->d_inode->i_version; bindex = au_dbstart(dentry); au_set_fbstart(file, bindex); btail = au_dbtaildir(dentry); au_set_fbend_dir(file, btail); for (; !err && bindex <= btail; bindex++) { h_dentry = au_h_dptr(dentry, bindex); if (!h_dentry) continue; h_file = au_h_open(dentry, bindex, flags, file); if (IS_ERR(h_file)) { err = PTR_ERR(h_file); break; } au_set_h_fptr(file, bindex, h_file); } au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ if (!err) return 0; /* success */ /* close all */ for (bindex = au_fbstart(file); bindex <= btail; bindex++) au_set_h_fptr(file, bindex, NULL); au_set_fbstart(file, -1); au_set_fbend_dir(file, -1); out: return err; }
int au_reopen_nondir(struct file *file) { int err; aufs_bindex_t bstart, bindex, bend; struct dentry *dentry; struct file *h_file, *h_file_tmp; dentry = file->f_dentry; AuDebugOn(au_special_file(dentry->d_inode->i_mode)); bstart = au_dbstart(dentry); h_file_tmp = NULL; if (au_fbstart(file) == bstart) { h_file = au_h_fptr(file, bstart); if (file->f_mode == h_file->f_mode) return 0; /* success */ h_file_tmp = h_file; get_file(h_file_tmp); au_set_h_fptr(file, bstart, NULL); } AuDebugOn(au_fbstart(file) < bstart || au_fi(file)->fi_hfile[0 + bstart].hf_file); h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC, file); err = PTR_ERR(h_file); if (IS_ERR(h_file)) goto out; /* todo: close all? */ err = 0; au_set_fbstart(file, bstart); au_set_h_fptr(file, bstart, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ /* close lower files */ bend = au_fbend(file); for (bindex = bstart + 1; bindex <= bend; bindex++) au_set_h_fptr(file, bindex, NULL); au_set_fbend(file, bstart); out: if (h_file_tmp) fput(h_file_tmp); return err; }
/* * after branch manipulating, refresh the file. */ static int refresh_file(struct file *file, int (*reopen)(struct file *file)) { int err, need_reopen; aufs_bindex_t bend, bindex; struct dentry *dentry; struct au_finfo *finfo; struct au_hfile *hfile; dentry = file->f_dentry; finfo = au_fi(file); if (!finfo->fi_hdir) { hfile = &finfo->fi_htop; AuDebugOn(!hfile->hf_file); bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id); AuDebugOn(bindex < 0); if (bindex != finfo->fi_btop) au_set_fbstart(file, bindex); } else { err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1); if (unlikely(err)) goto out; au_do_refresh_dir(file); } err = 0; need_reopen = 1; if (!au_test_mmapped(file)) err = au_file_refresh_by_inode(file, &need_reopen); if (!err && need_reopen && !d_unlinked(dentry)) err = reopen(file); if (!err) { au_update_figen(file); goto out; /* success */ } /* error, close all lower files */ if (finfo->fi_hdir) { bend = au_fbend_dir(file); for (bindex = au_fbstart(file); bindex <= bend; bindex++) au_set_h_fptr(file, bindex, NULL); } out: return err; }
static int reopen_dir(struct file *file) { int err; unsigned int flags; aufs_bindex_t bindex, btail, bstart; struct dentry *dentry, *h_dentry; struct file *h_file; /* open all lower dirs */ dentry = file->f_dentry; bstart = au_dbstart(dentry); for (bindex = au_fbstart(file); bindex < bstart; bindex++) au_set_h_fptr(file, bindex, NULL); au_set_fbstart(file, bstart); btail = au_dbtaildir(dentry); for (bindex = au_fbend_dir(file); btail < bindex; bindex--) au_set_h_fptr(file, bindex, NULL); au_set_fbend_dir(file, btail); flags = vfsub_file_flags(file); for (bindex = bstart; bindex <= btail; bindex++) { h_dentry = au_h_dptr(dentry, bindex); if (!h_dentry) continue; h_file = au_hf_dir(file, bindex); if (h_file) continue; h_file = au_h_open(dentry, bindex, flags, file); err = PTR_ERR(h_file); if (IS_ERR(h_file)) goto out; /* close all? */ au_set_h_fptr(file, bindex, h_file); } au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ err = 0; out: return err; }
int au_do_open_nondir(struct file *file, int flags) { int err; aufs_bindex_t bindex; struct file *h_file; struct dentry *dentry; struct au_finfo *finfo; FiMustWriteLock(file); dentry = file->f_dentry; err = au_d_alive(dentry); if (unlikely(err)) goto out; finfo = au_fi(file); memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); finfo->fi_hvmop = NULL; bindex = au_dbstart(dentry); /* * O_TRUNC is processed already. * But it is legal the target file has its size, since someone else may * give it while we are opening. */ BUG_ON(0 && au_test_ro(dentry->d_sb, bindex, dentry->d_inode) && (flags & O_TRUNC)); h_file = au_h_open(dentry, bindex, flags, file); if (IS_ERR(h_file)) err = PTR_ERR(h_file); else { au_set_fbstart(file, bindex); au_set_h_fptr(file, bindex, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ } out: return err; }
int au_reopen_nondir(struct file *file) { int err; aufs_bindex_t bstart; struct dentry *dentry; struct file *h_file, *h_file_tmp; dentry = file->f_dentry; AuDebugOn(au_special_file(dentry->d_inode->i_mode)); bstart = au_dbstart(dentry); h_file_tmp = NULL; if (au_fbstart(file) == bstart) { h_file = au_hf_top(file); if (file->f_mode == h_file->f_mode) return 0; /* success */ h_file_tmp = h_file; get_file(h_file_tmp); au_set_h_fptr(file, bstart, NULL); } AuDebugOn(au_fi(file)->fi_hdir); AuDebugOn(au_fbstart(file) < bstart); h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file); err = PTR_ERR(h_file); if (IS_ERR(h_file)) goto out; /* todo: close all? */ err = 0; au_set_fbstart(file, bstart); au_set_h_fptr(file, bstart, h_file); au_update_figen(file); /* todo: necessary? */ /* file->f_ra = h_file->f_ra; */ out: if (h_file_tmp) fput(h_file_tmp); return err; }